Posted by 미스란디르
Sun, 10 Feb 2008 18:33:00 GMT
GtkDrawingArea + Cairo를 이용해서 간단한 걸 만들고 있다.
그림판이랑 비슷한 부분이 아주 조금 있는데, 예를들면 어떤 그림 조각을 움직인다던가,
혹은 선택하고 복사해서 옆에 새걸 만든다던가 하는것.
C-c 로 복사하고 C-p 로 붙여넣고, DEL로 지우고 따위의 행동을 하려면 key-press-event를 사용하는게 좋겠다고 생각하고, gsignalconnect 로 연결해봤다.
그런데 시그널이 전혀 안들어온다. 참고로 button-press-event 라거나 motion-notify-event같은건 잘 받아진다.
그래서 구글에게 신탁을 해 보았는데, GtkDrawingArea 문서를 알려준다.
To receive mouse events on a drawing area, you will need to enable them with gtk_widget_add_events(). To receive keyboard events, you will need to set the GTK_CAN_FOCUS flag on the drawing area, and should probably draw some user-visible indication that the drawing area is focused. Use the GTK_HAS_FOCUS() macro in your expose event handler to decide whether to draw the focus indicator. See gtk_paint_focus() for one way to draw focus.
마우스 이벤트를 받으려면 gtk_widget_add_events() 를 해야하고, 키보드 이벤트를 받으려면 GTK_CAN_FOCUS flag를 세팅해야 한단다. GTK_HAS_FOCUS() 가지고 검사해서 뭔가 표시하라는건 덤이다.
그래서 다음과 같이 했다.
cpp:
widget = glade_xml_get_widget (xml, "drawing_area");
GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
g_signal_connect (widget, "button-press-event", on_button_press_event, NULL);
g_signal_connect (widget, "key-press-event", on_key_press_event, NULL);
.
.
.
gboolean on_button_press_event (GtkWidget *w, GtkEventButton *e, gpointer userdata)
{
gtk_widget_grab_focus (w);
return TRUE;
}
gboolean on_button_press_event (GtkWidget *w, GtkEventKey *e, gpointer userdata)
{
g_printf("%d:%d\n", e->state, e->keyval);
return TRUE;
}
focus를 가질 수 있게 하고, 버튼을 누르면 focus를 가져오게 한다. 그리고 key-press-event를 연결하면 끝. 아 사실 gtk_widget_add_events()로 이벤트 마스크도 더해줘야 하는데, 요건 글레이드 에디터에서 해버렸다.
아무튼 저걸로 잘 된다.
Posted in 프로그래밍 | Tags gtk, gtkdrawingarea | no comments | no trackbacks
Posted by 미스란디르
Sat, 26 Jan 2008 06:27:00 GMT
록형 블로그에서 지뢰를 밟았다.
물론 이걸 보신 분들도 마찬가지다.
지금 당장 작성해야된다니 어쩌겠는가.
자 그러면 시작
좋아하는 타입을 외양만으로 대답해 보자
김민정, 한지혜
연상은 좋아해?
약간.
휴대폰은 어떤 걸 가지고 있나요?
애니콜 V8900. 주머니에 넣고 다녔더니 쇠 부분 도금이 다 벗겨졌다.
휴대폰 고리는?
야후에서 받은 야후 로고 - 액정 클리너형.
수첩은 가지고 있습니까?
종이 쪼가리.
가방은 어떤 걸 사용합니까?
노스페이스 노트북가방(14인치용). 메고 있으면 왠지 공대생 필.
가방의 주된 내용은?
12인치 노트북, 책한권, 가끔 ndsl
별을 보면 무엇을 빌어?
별을 보며 소원을 빈게 몇년 전이더라?
만약 크레파스로 다시 태어난다면 무슨 색이 좋아?
주황색
좋아하는 요일
수요일. 이유는 없다.
마지막으로 본 영화는?
귀를 기울이면.
화날 때는 어떻게 해?
잠을 자거나 뭐든지 먹는다.
세뱃돈은 어디에 써?
통장에 넣는다.
여름과 겨울 중 어느 쪽이 좋아?
겨울.
최근 울었던 건 언제? 왜?
휴일 아침에 잠이 덜 깬 상태에서 갑자기 알 수 없이 서글퍼져서 이불속에서 막 울었다.
침대 아래에 뭐가 있어?
침대 안쓴다.
어젯밤 뭐 했어?
집에와서 동물의 숲 미아찾기를 했다.
우리 마을엔 미아가 참 자주 생긴다. 길이 어지러운가?
좋아하는 자동차는?
sm5-구형, 최근엔 i30이 너무 예뻐보인다.
돈 제한이 없다면 포르쉐.
좋아하는 꽃은?
라일락.
가고 싶은 나라는?
중국, 아프리카(케냐, 소말리아, 에디오피아), 그리고 오스트리아
Tags 낚시 | no comments | no trackbacks
Posted by 미스란디르
Mon, 21 Jan 2008 14:54:00 GMT

차드파울러 / 송우일 옮김 / 인사이트 / 2008
일단 칭찬부터
별 5개중에 별 4개 반. 별 다섯개짜리 책은 거의 없다는 걸 생각하면 - 영화도 마찬가지지만 - 꽤 좋은 책이라고 할 수 있다. 읽기 시작하면서 좋은 책이라고 느꼈고, 다 읽고 나서는 도시락 싸들고 다니면서 추천하고 싶은 책이 됐다. 물론 저자가 주장하는 내용중에는 무조건 동의하기 힘든 내용도 들어있다. 그러나 더 많은 수의 내용들에 고개를 끄덕이면서 동감하게 된다.
마틴 파울러와 친척이 아닌 차드 파울러
나는 차드 파울러에 대해 잘 모르고, 레일스 레시피에서 그의 이름이 들어간 챕터가 있다는 것 정도만 알 뿐이다. 마틴 파울러와 친척이 아니라고 강조하지 않았다면, 그가 마틴파울러의 동생쯤 되는 줄 알았을지도 모르겠다.
그가 어떤 경력을 가졌는지는 모르겠는데, 책에서 말하는 내용들을 보면 그가 새로운 것을 배우려고 하는 능동적인 개발자 - 혹은 리더 라는것을 알 수 있었다.
항상 자신을 가꾸라고 강조한다
그는 독자들에게 항상 새로운 언어를, 그리고 새로운 무언거를 배우라고 얘기한다. 현실에 안주해서는 안된다고 얘기한다. 하지만 현실에 불성실해서도 안된다고 말한다. 자기 자신에게 충실하고, 계발하라고 말한다. 그리고 그렇게 가꾼 자기 자신을 널리 알리는데 인색하지 말라고 한다.
책 중에서 재미있는 말이 있다.
구글은 모든 것을 기억한다.
구글에서 자기 이름이나 아이디를 쳐보면 그동안 써왔던 블로그나 게시물들, 오픈소스 참여기록등등, 공개된 메일링은 메일까지 찾아 볼 수 있다. 그렇게 여러곳에서 활동하면서 쌓아올린 인지도는 결국 자기 몸 값을 올리는데도 도움이 된다.
또한 업무를 할때는 개발 외적인 것에 대해서 무관심하지 말라고 말한다.
나는 비지니스에 관심을 가지고 전문가에 가까운 지식을 가지라는 말에 대해 무조건 찬성을 하지는 않는다. 때로는 숲을 보는 것보다 나무를 보는 것이 문제 해결에 도움이 될 때도 있기 때문이다. 하지만 숲을 알면서 시각을 한정시키는 것과, 아예 몰라서 볼 수 없는 것은 분명히 차이가 있으니 이것은 읽는 사람들이 판단할 문제이기도 하다.
미국과 한국 개발자와의 입장차이
책 중간중간에 미국인의 입장에서 인도로 IT인력 수요가 빠져 나가는 것에 대한 생각을 얘기 하기도 하는데, 이부분은 솔직히 실감하기 어렵다. 우리나라가 인도처럼 싼 IT인력시장도 아니고, 그렇다고 외주를 많이 주는 것도 아니기 때문이다. 그리고 책 후반은 약간은 지루한 느낌이 있다. 내가 졸려서 그런 것인지, 실제로 내용이 그런 것인지는 모를 일이지만.
하지만, 책을 읽고 나서 자신을 조금이라도 바꿔야겠다고 생각이 든다면 그것으로 충분하지 않을까. 실용주의 프로그래머를 읽었을 때와 비슷하게 자신을 좀더 사랑하고 계발해야겠다는 생각이 들었다. 아직 장래가 명확하게 결정되지 않은 내게 개발자로 살아가는 것이 괜찮을거란 생각을 갖게 해 주었다고 하면 좀 과장일지도 모르겠지만, 희망/불안 비율이 조금은 높아졌다.
깔끔한 번역
이 책을 권하는 또다른 이유로, 번역의 충실함을 들 수 있다. 300쪽에 달하는 책을 읽으면서 번역때문에 어색하다고 느낀 부분은 열 몇개에 불과하다. 번역을 해보신 분들이나, 혹은 IT 번역서를 읽어보신 분들은 이게 얼마나 대단한건지 알 수 있을 것이다. 역자이신 송우일씨는 프로그래밍 관련 편집일을 오래 하셨기에 관련 지식이 풍부하시고, 또한 글쓰기도 잘하신다. IRC에서 가끔 대화를 하는데 우일님이 맞춤법을 틀리면 화제가 되기도 할 정도다.
끝까지 칭찬
적어도 프로그래머라는 명함을 가지고 있는 사람에게, 혹은 프로그래머가 되고 싶은 사람에게 반드시 읽어보라고 권하고 싶은 책이다.
Posted in 독후감 | no comments | no trackbacks
Posted by 미스란디르
Sat, 15 Dec 2007 04:01:00 GMT
시작하기
요즘 동물의 숲을 하고 있다. 이거 무척 재미있는데, 게임이야기를 하려는 것은 아니고,
게임중에서 친구와 노는데 사용되는 wifi에 대한 이야기를 잠시.
※ 동물의 숲은 닌덴도 DS용 게임으로 wifi(네트워크 플레이)를 지원한다. 이하 동숲.
동숲을 하면서 혹시 86420에러를 본적이 있는가? udp에러라고 한다. 사실 몰라도 상관없지만.
아무튼, wifi를 통해 친구네 마을에 놀러가기도 하고 놀러오기도 하고 그러면서 노는데
나랑 할때만 안된다나 뭐라나. 자꾸 저 에러가 뜨면서 접속이 안되는거다. 수십번 하다보면 되긴 되는데,
그냥 잘 되는 사람들도 있거든. 그중의 한분은 네트웍을 상당히 복잡하게 쓰셔서 그 탓이 아닌가 하고
네트웍 설정을 보기도 했다. 참고로 그분의 네트웍은
ndsl ------- (노트북 무선랜 === 회사 유선랜) --------(VPN으로 어떤 서버에 연결) ------ (NAT를 통해서 외부로 연결) --------
이다. 그래서 VPN설정탓은 아닌지, NAT(리눅스에서 iptables로)탓은 아닌지 점검을 해 보았는데, 몇번 해봤지만 역시 될때는 되고 안될때는 안되더라
그래서 일단 어떤 일이 일어나는지 보기로 했다. 관심 없는 분은 10번으로 뛰어 넘으면 된다.
ndsl이 접속하는 과정 (놀러갈 때)
- 802.11b 네트웍으로 연결시도한다. DHCP로 세팅되어 있다면 아이피도 받아온다.
- http://conntest.nintendo.co.jp 로 간단한 GET 요청을 날려서 테스트페이지를 받아오는지 확인한다.
- acrossingds.available.gs.nintendowifi.net:27960에 udp패킷을 날리기 시작한다
- https://nas.nintendowifi.net 로 먼가 작업을 시작한다. 아마도 접속용 인증키를 발급 받는 것 같은데 https라서 까볼 수가 없었다 - 사실 여기서 squid를 가지고 중간자 공격을 시도했지만, 중간에서 가로채니까 ndsl이 바로 뻗어버렸다(이건 인증서가 달라져서 알 수 있는것 같다)
- gpcm.gs.nintentowifi.net:279990에서 challenge코드를 받아와서 다시 응답을 날린다. 그러고나서 다시 토큰을 받고, 자기가 등록한 친구들이 누구누구인지 서버에 얘기한다.
- http://www.nintendo.co.jp/ds/admj/oidydm/forestmailKOR.bin 로 GET요청을 보낸다. 결과데이터는 바이너리인데 뭔지는 모르겠다.
- acrossingds.ms12.gs.nintendowifi.net:28910 으로 역시 먼가 보내고 받는다
- acrossingds.natneg1.gs.nintendowifi.net:27901, acrossingds.natneg2.gs.nintendowifi.net:27901 로 "acrossing ds" 가 포함된 몇바이트짜리 udp패킷을 보낸다.
- 위에서 보낸 서버들이 뒤에 몇글자를 뺀 응답 패킷을 보낸다.
- tcp로 먼가 신호가 오고, natneg1:27901에서 상대편 아이피를 알려온다.
이제 어느 순간, 다음과 같은 패킷들이 오고간다. (111.111.111.57 은 상대편 공인 아이피, 222.222.222.57 은 내 공인 아이피)
22:13:50.458290 IP 111.111.111.57.1024 > 222.222.222.57.59375: UDP, length 20
22:13:50.460578 IP 222.222.222.57 > 111.111.111.57: ICMP 222.222.222.57 udp port 59375 unreachable, length 56
22:13:51.126067 IP 222.222.222.57.59375 > 111.111.111.57.63196: UDP, length 20
22:13:51.126120 IP 111.111.111.57 > 222.222.222.57: ICMP 111.111.111.57 udp port 63196 unreachable, length 56
원래는 서로 통신이 되야하는데, udp port unreachable이 발생한다. 대체 왜?
가만히 보니 포트번호가 이상하다.
내가 상대편에게 보낼때는 111.111.111.57:63196인데, 상대편이 보낼땐 111.111.111.57:1024 으로 온다.
복잡한 생각없이 보면 저게 쌍이 맞아야 할 것 같다.
그래서 계속 조사해보니 안될때는 계속 1024더라. 물론 저게 공유기 안쪽에서는 63196(이경우에는)으로 맞게 온다. 공유기가 바꾸는 것이다. 대체 왜?
wifi의 동작방식
여기서 또 잠깐. nintendo-wifi가 NAT-T(traversal)를 하기 위해 어떤 짓을 하고 있는지 보자.
원래 양쪽이 공유기이면 서버를 통하지 않고는 p2p 통신을 하기가 어렵다. msn에서 하고 있는 짓을 보면, 파일전송 따위의 p2p통신을 할 때
각각 서버를 열어서 상대편 서버로 접속 시도를 해보고, 되는 쪽으로 통신을 한다. 한쪽이 공인아이피를 그대로 쓰고 있다거나 DMZ를 쓴다면 그걸로 ok.
만약 양쪽 다 공유기라면 서버를 통해서 간다. 무슨 소리인지 모르겠다는 분은 그냥 넘어가자.
그런데 DS는 일단 무선랜이고, 인증기능도 단순하기 그지 없다. 따라서 상용 무선 인터넷 보다는 집에서 공유기로 접속할 확률이 3만배 많다. 즉 p2p에 있어서 최악인
공유기 vs 공유기인 설정. 그런데 똑똑한 닌텐도 개발자들은 재미있는 트릭을 썼다. 공유기 때문에 고민한 개발자라면 어떻게 안될까?.. 라고 생각해본적이 있을지도 모르는 트릭이다.
위에서 8번, udp패킷을 서버에 보내는 장면. 이때 서버는 저 패킷을 통해서 ds wifi 패킷이 처한 공유기 환경을 인식한다. 즉 외부 공인아이피가 뭔지를 확인하는 것이다. 그리고 아마도 10번에서 udp패킷으로
상대편 공인 IP / PORT 를 알려준다. 받자마자 ds는 접속시도.
공유기의 동작방식 - NAT가 무엇인가
이제 공유기에서는 어떤일이 일어나는가? 공유기들이 편리한 인터넷 환경을 위해서 무엇을 구현하고 있는가를 알아야 한다.
NAT(Network Address Translation) 은 S-NAT과 D-NAT이 있다. S-NAT은 흔히 말하는 인터넷 공유, 즉 소스 아이피를 바꿔주는 것이다.
D-NAT은 흔히 말하는 포트포워딩에 해당한다. 즉 목적지 주소를 바꿔주는 것이다. 공유기에서 S-NAT 설정을 하게 되면,
조건에 맞는 패킷이 지나갈 때 소스 아이피를 바꿔준다.
예를들면,
192.168.0.3: 공유기 안쪽 PC
192.168.0.1: 공유기 LAN쪽 IP
211.211.211.100: 공유기가 가진 공인 IP
100.100.100.100: 접속하려는 서버
192.168.0.3:54321 -> 100.100.100.100:80 LAN에서는 이랬던 패킷이,
====> 211.211.211.100:54321 -> 100.100.100.100:80 요렇게 변한다.
여기서 192.168.0.3:54321 -> 100.100.100.100:80 이나 211.211.211.100:54321 -> 100.100.100.100:80 을 tuple이라고 하고,
요것 두개를 묶어서 tuple pair라고 하자.
이게 변할 수 있는 것은, 외부로 나가는 패킷의 소스 주소를 211.211.211.100으로 변환해달라는 '규칙' 이 있기 때문인데, 들어오는 규칙에 대해서는 따로 설정을 한 적이 없다. (※ 나가는 규칙도 아이피를 직접 쓰는 일은 거의 없는데, 이건 MASQUERADE라고 해서 나가는 인터페이스의 IP주소를 그걸로 쓴다고 약속하기 때문이다)
그러면 응답패킷이 오면 어떻게 할까?
100.100.100.100:80 -> 211.211.211.100:54321 공유기 밖
====> 100.100.100.100:80 -> 192.168.0.3:54321 공유기 안쪽
가만히 보면 위쪽거랑 거꾸로다. 요걸 inverted tuple이라고 부르자.
이걸 보니, 나가는 패킷이랑 반대로 변환하면 다시 들어오는 패킷도 처리할 수 있을 것 같다.
즉 패킷이 하나 나가면 위의 4가지 정보(혹은 inverted는 생략하고 2가지만)가 공유기의 메모리 어딘가에 딱 생긴다. linux 는 요걸 conntrack (connection tracking)이라고 부르고 /proc/net/ip_conntrack 에서 볼 수 있다. 얘네들은 보통 상태정보도 가진다. tcp라면 SYN 보냄, SYN-ACK 받음, ACK 보냄(ESTABLISHED) 뭐 이런식이다. 또 패킷이 한쪽으로만 가고 한쪽으로 안갔다면 UNREPLIED. 양쪽 다 갔다면 ASSURED라는 딱지가 붙기도 한다.
그런데
가끔 재미있는 경우가 생긴다.
패킷 주소가 변환되는 과정을 다시 한번 보자.
PC가 한대가 아니라 2대이고, 우연히도
192.168.0.3:54321 -> 100.100.100.100:80
192.168.0.4:54321 -> 100.100.100.100:80
이라면,
먼저 온쪽이
211.211.211.100:54321 -> 100.100.100.100:80
을 차지하게 된다.
그럼 또 한놈은? 저걸 또 쓰면 겹치니까 그럴 수는 없고(응답 패킷이 왔을때를 생각해보자. 어찌 되겠는가. 혹은 서버입장에서도 마찬가지) 적당히 다른 번호를 준다.
211.211.211.100:1024 -> 100.100.100.100:80
왜 하필이면 1024인가 하면, 1023번 까지는 중요 포트라서 시스템에서만 쓰도록 하게 둔다. 이것보다 넓게 잡는 os도 있다.
이제 원인을 반쯤 알아냈다. 안될때 1024로 되는 이유는 바로 이거다.
.
.
.
아하
이런 경우는 정말정말정말정말 우연히 일어나기 때문에, ds에서 자꾸 접속이 안되는건 설명이 안된다. 그 수많은 pair가 겹칠리가 있는가? ds가 두대인것도 아니고. 같은 포트를 쓰더라도, 상대편 주소가 다르면 상관 없기 때문에 겹친다는건 말이 안된다.
사실 위 메커니즘을 다시 떠올리느라고 오랜만에 netfilter 소스를 돌아다니면서 기억을 되짚었다. 그러다가 생각난 "아하!"
바로 UNREPLIED conntrack의 존재이다.
222.222.222.57:59375 -> 111.111.111.57:63196
으 로 패킷이 갔다고 치자. 그리고 그게 111.111.111.57 공유기에 도착을 했다. 그런데, 111.111.111.57 공유기에서는 아직 자기쪽 DS에서 패킷이 안나온거다! 그럼 아무정보도 없는 공유기는, 지금 온 패킷을 진짜 자기에게 온 패킷으로 가정하고 시스템한테 던진다. 시스템에서는 이 패킷에 해당하는 listen 소켓이 없으니까 없다고 udp unreachable ICMP메시지를 날린다. 동시에, conntrack에는 이 패킷의 tuple이 UNREPLIED로 등록이 된다(!). 여기서 눈치 챘으리라. 정작 자기 DS에서 나온 패킷이 나갈 때, 이 포트를 쓸 수가 없는거다. UNREPLIED이지만 사용중인 것처럼 보이는거다.
아아 그렇다. 게다가 접속 시도 때문에 이쪽으로 패킷이 계속 오니까 이 tuple 정보는 없어지지도 않는다. 결국 접속시도는 실패.
근 데 양쪽에서 동시에 접속 시도를 한다고 하면 왜 이런일이 생길까? 이유는 간단하다. 네트웍 속도는 동일하지 않기 때문이다. A공유기에는 10ms 만에 서버에서 신호가 오고, B공유기에는 100ms 만에 왔다고 치면, B공유기까지 가는동안 A공유기를 거쳐서 들어갔다가 DS가 다시 응답하는데 충분한 시간일 수도 있다. 그리고 선로 속도는 평균이 있어서 쉽게 변하지 않기 때문에, 우연히 서버와의 속도만 나쁜 회선 사용자가 있다면 저 현상은 쉽게 고쳐지지 않을 것이다. 방법은 반대쪽 사용자가 DMZ같은 세팅을 하는 것 뿐.
사실은 공유기에서 저 UNREPLIED tuple을 만들지 않으면 되는건데.. 그게 실제로 unreachable일 경우에 그렇게 하면 안되는 이유라도 있는건지 모르겠다.
그래서 내가 떠올린 해결책 하나.
ds 에서 접속 시도 패킷을 쏠때, TTL을 1부터 시작해서 하나씩 늘리는거다. 그럼 공유기를 한단계씩 지나가겠지만, 그렇다고 상대편 공유기한테 바로 도달하지는 않는다. 이런식으로 길을 하나씩 뚫으면서 가면, 몇중으로 공유기로 둘러쌓인 환경이라도 문제 없지 않을까.
오늘따라 너굴 상점이 증축공사로 휴업을 하는 바람에 심심해서 써봤다. 재미없는 글 여기까지 읽어주시느라 고생하셨다.
Posted in 리눅스 | Tags 동물의숲 | 9 comments | no trackbacks
Posted by 미스란디르
Sat, 03 Nov 2007 19:10:00 GMT
언제부터인가 괜히 자전거 여행같은거 하면 좋겠다는 생각을 가지고 있었다. 허니와 클로버에 나오는 타케모토의 자신을 찾는 여행을 보고 동경했기 때문이다. 이거 멋있네 하고.
그리고 이름만 들어온 저 책을 보게 되었다. 책을 읽으면서 내내 느낀건데, 글 참 못쓴다. 아니 뭐 그렇다고 진짜로 못쓰는건 아니다. 단지 작가라기보단 아마추어 수필가 수준. 근데 읽다보면 가슴이 찡 할때도 있고, 방바닥을 뒹굴면서(진짜로 뒹굴었다) 웃기도 하고, 한 없는 슬픔을 느끼기도 했다.
훌륭한 재료를 가지고 요리를 만들때는 재료를 크게 손대지 않는 수준에서 요리할 때 훌륭한 맛을 내는 것 처럼, 훌륭한 경험을 투박한 문체로 쓴 이 책은 감동이 무엇인지 느끼게 해 준다. 살아있는 경험은 정말 맛있다. 이걸 요리로 치면 참치 대뱃살 정도 되겠다.
7년이란 긴 시간을 투자할 용기는 없지만, 그래도 떠나볼 것이다. 멀리가지는 않을테지만, 어쨌든 달려볼테다. 그리고 많은 사람들과 많은 것들을 만나면 좋겠다.
Posted in 독후감 | Tags 자전거 | 2 comments | no trackbacks