IPC on iOS7 with Evais0n
IPC, Inter Process Communication..
말 그대로 프로세스 간에 통신을 위한 방법이다.
예전에 deVbug 님 글에 몇가지 소개가 있었는데 ... IPC (Inter Process Communication) in iOS
나도 이것에 대해 잠깐 끄적여 볼까 한다..
BeeKeyboard 의 온갖 버그의 주범이자, BeeKeyboard 가 iOS7 대응하는데 2달이나 걸리게 한 장본인이기도 하다.. orz
IPC 자체에 대해 쓰기보다는, iOS7 의 강화된 샌드박스에 의해 IPC 를 제대로 사용하지 못하면서 생긴 문제와 그를 풀어갔던 삽질.. 에 대해서 써볼려고...
BeeKeyboard 업데이트 일기..? 의 느낌으로 써보려 했으나 글의 목적에 어긋나는 것 같아
BeeKeyboard 보다는 IPC 자체의 삽질에 좀더 초점을 맞춰보려 한다.
일대기.. 식으로 회상하면서 써내려 갈 거임!! ㅋㅋㅋ
시작하기 전에 IPC 에 대해 잠깐 정리.
- mach_msg : 기본적으로 모든 IPC 는 mach_msg 라는걸 기본으로 한다. 그런 만큼 얘는 매우 low level 이고, 메세지 하나 보내는데 20줄 가까이를 요구한다.. 래핑하지 않으면 더럽게 쓰기 어려운 녀석이지.. Ryan Petrich 의 LightMessaging 이 얘를 래핑했다. 나의 경우 BoatMessaging 이라는 녀석으로 래핑해서 사용 중.
- CFMachPort : mach_msg 에 쓰이는 mach_port_t 를 위한건데.. 한단계 래핑했다기 보다는 그냥 같이 쓰인다
- CFMessagePort : 좀 쓸만하게 래핑된 프레임워크. 양방향 메세징을 지원하며 내가 주로 사용했다ㅋㅋ
- CPDistributedMessagingCenter : 마찬가지로 양방향 메세징을 지원하며, CFMessagePort 보다 한층 더 쓰기 쉬우나, 자질구레한 문제가 많이 일어난다. 내가 제대로 못써서 그런거일 수도 있고...BeeKeyboard 의 iOS5 시절에 사용했었다.
뭐 이정도..? 당연히 더 있지만 일단 지금 글에선 필요없다.
1. iOS7 의 강화된 샌드박스
그냥 더 많은게 안된다. 시스템 로그를 보면, 앱스토어 앱이나 시스템 기본 데몬들도 sandbox 에 의해 좌절하는 로그를 무수히 쏟아낸다...
특히 CFMessagePort 의 경우 본래 앱스토어 앱에선 사용 못할텐데 맥 레퍼런스에서
"This method is not available on iOS 7 and later—it will return NULL and log a sandbox violation in syslog."
라고 친절히 알려주기 까지 한다.. ( 출처: 애플 레퍼런스 )
2. 근데 왜 제목에서 with Evais0n??
사실 BeeKeyboard 는 본래 iOS7 탈옥이 나오기 전에 winocm의 opensn0w 를 이용한 아이폰4 반탈로, iOS7 에 대한 대응이 되어 있었다.
탈옥할 때 탈옥툴 개발자들이 sandbox 를 깨주는데(그래야 트윅이 사용가능 하므로) 이 작업을 evais0n 탈옥팀은 뭔가 반틈만 한게 아닌가.. 라고 생각하고 있다. 물론 1번의, Apple 의 강화된 샌드박스도 한 몫할 것이고.
3. 삽질의 시작.
진짜 처음엔 답이 없어보였다.. 자고 깨고 자고 깨고(일이 잘 안풀리면 급격히 졸려서 1~2시간쯤 자고 일어난다)를 반복하며 1주일 가까이를 헤맸었던 것으로 기억한다.(심지어 이땐 RocketBootstrap 이 없거나, 개발 중이였다)
요즘 오전 6~7시에 취침 하고 오후에 일어나는, 6시간쯤 비틀린 삶을 사는데 그 원인이 여기에 있나니...
여튼 sandbox 에 의해 막히지만, privileged process, 즉 backboardd 나, SpringBoard, 혹은 Preferences 같은 시스템 앱들은 정상 사용이 가능하다. 하지만 난 일반적인 앱 모두에서의 사용을 필요로 했다. 단방향이 아닌 양방향.
4. XPC, WaveMessaging!
처음으로 가능성의 빛을 본 건 xpc. iOS5 정도 부터 iOS 에 들어간 것으로 보이고, 맥에서 IPC 로 애플이 추천하는 방법이다.
양방향 통신도 가능하고... 데이터형을 모두 xpc_object_t 를 사용해서 변환작업이 있다는 것만 제외하면 쓸만했다.
하지만 이 방법의 단점은 plist 에 특정 이름을 쓸거라고 미리 지정을 해 줘야 한다. 그렇지 않으면 사용할 수 없음...
launchd 가 관리하기에 후킹도 불가능하다...
그래서 난 원래 시스템이 사용하는 xpc 를 빌려, 적절히 후킹해서 사용하기로 했다.
그 결과물이 WaveMessaging. 좀더 자세한 방법은 써봤자 모를테니 패스..
open source... 지만 쓸 일 없을거다.. 써서도 안되고. 혹시나 xpc 를 쓸 일이 있으면 참고가 되려나?
소스: https://github.com/iolate/WaveMessaging
5. Optimo의 리젝...orz
SimulateTouch, BeeKeyboard, QuickKakao 프로토버전 등, IPC 가 필요한 앱에 모두 이식을 해 보았다.
결과는 대 성공! 모두 정상작동 하고 큰 문제도 없어보였다.
일단 WaveMessaging 패키지만 먼저 BigBoss 에 업로드 하였으나 돌아온 대답은 No!
이미 RocketBootstrap 이라는, 같은 목적의 패키지가 있으니 이것과 합치는 방향으로 가라는 것이다.
당시 RocketBootstrap 은 SpringBoard 를 기반으로만 작동하였고, LightMessaging 이 사용하는, mach_msg 와 이미 문제때문에 사용하지 않는 CPDistributedMessagingCenter..정도만 지원하였기에 나의 경우엔 쓸 수 없었다.
Optimo 에게 요구해 보았지만, 돌아온 대답은 "Ryan 과 잘 얘기해서 RocketBootstrap 으로 합치거라."
6. Ryan 의 CFMessagePort 지원
Ryan 은
1. CFMessagePort 혹은 xpc 를 지원하고 2. daemon 등에서도 사용가능 하게 해주겠다.
면서 몇일만 기다려 달라고 했다.
별 수 있으리.. 기다렸다. 며칠 후 RocketBootstrap 은 CFMessagePort 를 지원하였고, 잘 작동하는 듯 보였다.
하지만 일이 이렇게 쉽게 풀렸으면 이 글을 시작하지도 않았다..ㅠㅠ
일반 App -> SpringBoard, backboardd 는 정상적으로 사용이 가능해 졌지만, SpringBoard, backboardd -> App 은 사용이 불가능 했다!
App 위에서 CFMessagePort 의 서버를 돌렸는데 mach_lookup 뿐만 아니라 mach_register 까지 sandbox 에 의해 막히면서 크래시....
SimulateTouch 의 경우 이정도 만으로 충분히 사용이 가능했지만, BeeKeyboard 와 후에 만들 빠른 답장 트윅에선 곤란했다.
Ryan 에게 요구했으나 이건 자기도 어쩔 수 없다며, 다른 방법을 찾으라고 했다..
7. 결국 mach_msg
Ryan 이 나에게 왜 그런 기능들이 필요하냐고 물었다. 그래서 나는 BeeKeyboard 의 동작 원리와, 후에 만들 빠른 답장 류의 앱에 대해 간략히 설명해줬다. 음.. 여기는 말로 풀어내기 복잡하니 대충 건너뛰고 결론은
1. timeout 기능은 mach_msg 로 가능하다
2. xpc 또한 mach_msg 로 만들어 졌다. 니가 xpc 에서 사용하던건 mach_msg 로 구현이 가능하다
.... 별 수 있나.. mach_msg 로 시도했다.
xpc 를 떠올리며 최대한 흡사하게 흉내낸 후, 결과는 성공.
Ryan 의 LightMessaging 의 소스를 많이 참고하였지만, 그래도 생각보다 쉽게 해결되서 상당히 허탈했던 기억이....
Ryan 에게 확인을 구하니 접근은 정확하게 맞았고, 방법에 약간의 수정을 가하면 된다고 하였다.
이렇게 해서 mach_msg 로 내가 원하는 기능을 정확히 구현...
위에 말했듯이, mach_msg 를 그대로 사용하는건 토나오므로, BoatMessaging 이라는, CPDistributedMessagingCenter 와 CFMessagePort 의 사이.. 정도 수준으로 래핑한 스태틱 라이브러리를 만들었다.
이걸로 IPC 해결!!!
이렇게 까지 오는데 한달 넘게? 거의 두달? 여튼 엄청난 시간을 쏟아 부었던 것 같다..ㅠㅠ
BoatMessaging 의 소스나 하다못해 라이브러리라도 어디 올릴까 했지만,
살짝 꼼수스러운 라이브러리이기도 하고, 레퍼런스 등을 만들기 귀찮아서 일단은 그냥 나 혼자 쓰고 있다.
혹시나 필요하시면 연락주세요..ㅋㅋㅋ 기쁜 마음으로 공유해드립니다! ㅋㅋㅋ
이래봤자 요구할 만한 사람은 상당히 한정되어 있지만....
탈옥 개발자에, 한국어 사용자.. 몇이나 되겠어?
만들 당시 Source Control 켜서 쓰고 있었길래 그냥 그대로 github 에 올렸다.
주소는 https://github.com/iolate/BoatMessaging
static library 에,, rocket bootstrap 을 필요로 하므로, 사용하려면 LDFLAGS 에 -lboatmessaging -lrocketbootstrap
둘다 해줘야 함...
여튼,, 수능이 끝난 잉여로운 고3이였기에 해결이 가능했던 것 같다..