Some tricks in passing file descriptors through unix domain socket

Passing file descriptors through unix domain socket is well-known. But there still have some tricks in implementation. I spent one day to deal with it in Mac OS X by digging into xnu source.

  1. How to pass multiple file descriptors in one sendmsg() call>

    Simple. Put all file descriptors one by one after struct cmsghdr.

  2. Can I put multiple struct cmsghdrs with data? I noticed there are CMSG_FIRSTHDR() and CMSG_NXTHDR() defined in <sys/socket.h>

    No. In xnu sources it checks msghdr.controllen with cmsghdr.cmsg_len. If they are not equal, a -EINVAL returned in sendmsg() call. That means only one cmsghdr can be put into msghdr.

The limitation is in OS X only. I haven’t check Linux and would do it soon or later.

Auto Layout UITableView cell resizing with multi-line UILabel issue in iOS7

There are many blogs and articles talked about this issue and resolution on Internet. But any of them has this or that problems in those solutions. So I took several hours on researches and got a perfect result, at least I think so. 🙂

Thought about device orientation change, table width and cell width will change. And since we are already use Auto Layout here, it is not a good practice to design cell with any implicit width, say, 320. in Interface Builder. Almost all solutions on Internet assumed 320 width implicitly so those solutions would fail on either landscape orientation, or, iPad if the app is a universal app and you use same cell design for both iPhone and iPad.

So, the problem is in [tableView: heightForRowAtIndexPath:] delegate method. This delegate method is required for iOS7 or the app would crash. To return a correct height value of the cell, we need those steps:

  1. Set cell width to table width after loaded the cell from xib.
  2. Set values for widgets including multi-line UILabel inside cell
  3. Call [cell setNeedsLayout] and [cell layoutIfNeeded]. After those 2 calls, system’s layout engine would set correct width for UILabels. Note at this time the label’s preferredMaxLayoutWidth is still zero or any value left from last using so the layout engine cannot wrap lines and adjust label’s frame correctly.
  4. Set label.preferredMacLayoutWidth = CGRectGetWidth(label.frame)
  5. Call [cell setNeedsLayout] and [cell layoutIfNeeded] again. This time labels have correct preferredMaxLayoutWidth and the layout engine would adjust label’s frame correctly
  6. Now you can call [systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] to get correct height.

Solutions on Internet usually don’t do step 1 and 5. In an invariant screen size they can get correct display but they are not a real solution for other cases.

However, from iOS8 there is a simple solution. Apple solved the issue. Just returning UITableViewAutomaticDimension or just not implementing the method will get correct result. But for apps having to maintain compatibility with iOS7, we still have to do something like this.

国内网盘的 API 服务粗览

因为要写一个从云端读取文件的程序, 首先想到的自然就是目前各家火爆的网盘服务了. 于是今天就花了点时间, 逐个看了一下. 当然, 因为是要写程序嘛, 所以网盘是否提供 API 当然就是重点了. 除了 API 之外, 也要能方便地从浏览器访问, 这样程序才有东西可以读, 对吧.

1. 百度云网盘

原来是有开放 API 的, 叫 PCSAPI (个人云服务), 但是现在已经不支持了. 新的移动接入方式在内测中, 只支持 Android, 并且需要申请. 申请表格中需要填写申请者详细信息以及应用本身的信息和下载方式. 申请之后需要审核, 也不知道要审核多久会不会有回应. 另外, 作为一个需要从云端下载文件的应用, 在你云端都还没有让我访问之前, 我怎么可能有应用存在并供你下载?

另外, 这个 android 的 SDK 还需要你在手机上安装了百度云的 app 才能工作.

2. 360 网盘

不支持 API.

3. 微盘

微盘有公开 API 支持, 开发者简单创建应用后即可使用. 很好. 但是微盘有个应用间微盘空间隔离的策略. 也就是任一应用都不能访问别的应用的存储空间, 也不能访问在 web 上访问到的微盘内容. 从 web 微盘页面上, 也看不到应用的存储空间. 这对于要从 web 传文件而应用只是下载的情形就不行了. 当然, 微盘也还是有可以访问全部空间的选择项的, 只不过也需要申请并审核. 不知道要审核多久会不会有回应.

4. 华为网盘

华为 dbank 网盘做得其实也挺早的, 然而华为做云服务好象总是做不好. 目前华为网盘的注册登录界面到处都有 connection reset 的错误, 连正常的注册登录都没法完成, 让人觉得是不是已经没人维护, 准备抛弃了.

5. 腾讯微云

腾讯微云的 API 是夹杂在一堆无关的 QQ API 中间的. 最要命的是, 腾讯注册开发者需要你上传 “手持身份证” 的照片. Why? 实名登记以便跨省?

6. 115 网盘

115 曾经名声响亮. 然而, 打开 115 首页, 赫然要求只能用 115 浏览器登录, 或者用 115 手机 app 扫码才能登录. 我勒个去, 吃相也未免太太太难看了吧?

7. 金山快盘

注册用户时报错 “服务器正在维护中”, 用个第三方帐号登录进去, 对网盘的页面随便做什么操作都会显示 “服务维护中” 的信息. 同样让人觉得是不是没人维护即将关闭了.

8. 酷盘

 

9. 千易 1000eb.net

只支持网页中嵌入上传文件到千易, 以及为上传的文件提供一个下载链接. 没有 API.

10. 七牛

七牛的 API 比较完整. 然而它不是做网盘的, 它是做云存储服务的. 它没有面向普通用户的 web 网盘操作界面.

结论

好象想不出来别的网盘服务了. 国内比较流行知名的面向普通用户的网盘也就这些了吧, 然而, 结果是, 没有一个能够提供方便的 API 供第三方应用使用. 这其实正是你国互联网界的一个缩影, 外表光鲜, 热闹非凡, 内里却都是破棉絮.

Odd behavior in Windows Service status reporting from recent Windows 2008 R2

I have a Windows service program written many year ago and the user asked me to fix an issue that occurs recently in Windows 2008 R2. Indeed it is not a big problem but quite annoying. When the user stops the service, Windows always popup a window showing an error message like “Windows could not stop the […] service on local computer, The service did not return an error.” Damn it! How could you show me an error dialog with no error message?

Google doesn’t have any similar case like this. So I have try this and that, here and there.

OK, everybody knows that kind of experiments are boring and time consuming. So I just expose the answer.

In the service’s control handler codes for SERVICE_CONTROL_STOP, I reported a SERVICE_RUNNING status followed by a SERVICE_STOP status. That works without any problem before, but caused the issue in recent 2008 R2. After I changed the first status reporting to SERVICE_STOP_PENDING, the dialog disappears.

It looks like Windows doesn’t accept SERVICE_RUNNING when it sent to services SERVICE_CONTROL_STOP. But can you show me a clear error message?

 

Object subscripting in objc

Object scripting what use something other than an integer inside []. For example, dictionary[@”key”] = @”value”

And in generated machine code, it is a call to selector

-(id) objectForKeyedSubscripting:(id)key

An informal protocol named __ARCLiteKeyedSubscripting__ was defined

@protocol __ARCLiteKeyedSubscripting__
– (void)setObject:(id)arg1 forKeyedSubscript:(id)arg2;
– (id)objectForKeyedSubscript:(id)arg1;
@end

Built-in types like NSDictionary already implemented this protocol, which is indeed generated by compiler. For custom types, just implemented those 2 methods and everything will work.

Some license checkpoints in Reveal app.

  1. [IBAAppDelegate applicationDidFinishLaunching:] would call [IBAAppDelegate verifyCodeSignature] to verify code signature of the app to prevent itself from modifications.
  2. [IBATrialModeReminderPresenter shouldShowTrailModeSheet] controls whether trial mode sheet, including quit after trial period expired, would be shown.
  3. [IBAMainWindowController configureTitleBarAccesoryView] will create IBATrialModeReminderTitleBarAccessoryView to shown trial information on window’s title bar.

That’s all.

Make IB designed view work with iCarousel

Oddly, View designed in IB would have FlexibleWidth+FlexibleHeight set in it autoresizingMask, even if you cleared everything in auto resizing box, regardless using AutoLayout or not. The behavior causes that subviews inside item view have wrong positions after transform3D with rotations. In short, item view’s width/height in subviews position/constraints calculation would be calculated as rotated value instead of  preset value, 

The solution is put self.autoresizingMask = 0 to awakeFromNib, easiest? But it took me 1.5 days to find the reason.

XcodeGhost, 墙, 全民编程, 以及未来

这些天 XcodeGhost 闹得沸沸扬扬. 作为一个好歹写程序的年头比 Twitter 或者 Weibo 上大多数人长的老程序员来说, XcodeGhost 本身其实并没什么高深之处, 也没有什么出乎意料的巨大危害. 甚至, 把它称为病毒也是错误的, 最多不过是个 malware 而已. 并且, 相对于国内 Windows desktop 以及 Android 系统里的 malware 们而言, XcodeGhost 太小儿科了. 好歹 iOS 的 sandbox 还控制着权限, Windows 全家桶们可是早就把你的底裤都翻光了. 没见着有这么激动嘛.

我赞同云风的观点, 这个玩意跟你 link 了一个谁谁谁的什么分析跟踪, 广告展示, 乃至于流行的支付, 分享等等的 SDK 进去没有任何差别. 技术一点说, 两者都是把一些代码加入到了你的应用中, 并且在某些时候会得到执行.  弹窗骗用户帐号密码? 都可以. 发送一些用户信息到远端服务器上? 都可以. 安装企业证书签名的 App? 都可以. 顺便说一下, 国内对企业证书的滥用才是比 XcodeGhost 更大得多危险得多的安全漏洞.

究其原因不能不说到墙. 然而不是说把责任都推到墙上就完事了的. 需要想一想为什么这样, 以及这又反映了什么.

首先, XcodeGhost 这个东西也是只有在国内这个环境里才会造成这么大范围的传播和扩散. Yes, 墙功不可没. 不过试想一下, 假设现在把墙撤了, 我认为 XcodeGhost 还是会同样大量迅速扩散的. 对于多年来习惯于四处下载盗版音乐电影软件的毫无职业素养和基本常识的你国众多小白程序员和产品经理来说, 对, 像 adoal 说的, 连免费软件都要盗版的人来说, 扔到迅雷上去或者从百度云盘拉, 必然会是比从 Mac App Store 或者 Apple developer site 下载安装更优先的选择. 再往深了想原因就是多种互相纠缠在一起了, 恕不赘述. 想探讨的请我吃饭咱们边吃边聊好了. 哈.

然后回过来说墙. 经过从计算机萌芽期开始长期不懈的盗版洗礼, 以及 10 年左右的强有力的寡妇网封锁. 你国小白们, 不光是普通用户, 连程序员都是, 已经不知不觉地形成了相当完整的墙内思维了. 搜索上百度, 软件下盗版, iOS 用 XX 助手, Malware 遍地的 android 商店们就更不用说了. 大家的整个计算机生存环境已经是与你国以外用户完全不同的一个环境了. 很好, 非常好. 我觉得可以说, 大中华局域网已经基本完成了. 别说我危言耸听, 看看: 与世界隔离, 需要的所有东西都可以在内网设法找到无论什么途径来源如何, 这不是局域网是什么? 说件更悲哀的事, 跟十几岁的孩子们聊天, 已经几乎没有人知道 Google 是什么了. 这不能怪他们, 一个不能访问的网站, 自然就相当于不存在. 物理封锁其实还不算什么, 思维被封锁了, 才是真正的被封锁. 就如今的情形看, 我持悲观态度.

这个问题就到此吧, 我比较不喜欢煽情, 无论是热烈吹捧还是血泪控诉. 有脑子的人自己会去体会. 别老替别人哭和笑.

然后是全民编程. 这个话题这几年热得发烫. 然而对照 XcodeGhost 干了什么, 再想一想. 至少我觉得在目前, 全民编程这个想法很傻冒, 跟天真, 十分类似于别有用心的人提出来的. 连目前算是专业的程序员们都缺乏基本的编码常识, 你让见到随便哪个提示框就乖乖地把自己的帐号密码输进去的“民”来编程? 别说我阴谋论, 至少我是绝对不敢用这种民编出来的程的.

说到这里就是 IoT 了, 全民编程是在这个背景下提出来的. 我相信未来是人机结合体的时代, 但是安全是最大的问题. 从这个意义上讲, 未来还是有漫长的路要走, 因为, 信任这一安全上至关重要的点, 至今还是很难保证的. 是的, 我信任从 Mac App Store 安装的 Xcode, 但是我无法确认别人也是从 Mac App Store 安装的而不是从迅雷或者百度下载的带有 XcodeGhost 的. 所以, 这还是个难题, 除非所有代码都是我自己写的, 问题是, 我写得过来吗?

iOS BLE application restore

According to Apple’s documentation, Bluetooth related app can assign a restore identifier to itself so that it can be re-launched by system when BLE events arrived and the app has been killed by System. I made a test on this and found some facts Apple didn’t describe it clearly.

  1. If the app got killed by system due to resource limitation, it exactly can be re-launched, as Apple’s Core Bluetooth Programming Guide described.
  2. If the app got killed by user sliding up the app card away, it won’t be relaunched
  3. If the app connected to a bluetooth peripheral, it looks like the system assigned it a high priority so it is unlikely to be a candidate when system needs killing something.
  4. After centralManager:willRestore: method, centralManager:didUpdateState: is always got called,  so let the latter handle both the cases of normal launching and re-launching by system is OK.

Therefore, there is still no safe way to handle BLE communications in background since user can always kill the app, and it is usual for us iPhone users.

Just found 2 issues in apple’s assembler for arm64

1) The classic ‘@‘ comment indicator is not recognized in -arch arm64 mode. Both ‘;‘ and ‘//‘ are permitted. I remembered ‘@‘ was acceptable in armv7 age. So the world changes so fast…

2) As ARM’s instruction reference manual, the instruction ‘movi‘ has a format as

MOVI Vn.<T>, #uimm8{, LSL #shift}

But as reported error if we omitted last part. So to make assembler work, I have to append a ‘LSL #0’ to the end. Feel somewhat stupid, for both the assembler and myself 🙂