Mercurial > pidgin
comparison src/stun.c @ 11336:7d7dd22215ec
[gaim-migrate @ 13549]
STUN NAT discovery from gaim_network_get_public_ip
committer: Tailor Script <tailor@pidgin.im>
author | Thomas Butter <tbutter> |
---|---|
date | Wed, 24 Aug 2005 20:45:20 +0000 |
parents | dd1a5969b2e5 |
children | 97028c1c69e9 |
comparison
equal
deleted
inserted
replaced
11335:59aa7080eb2d | 11336:7d7dd22215ec |
---|---|
1 /** | 1 /** |
2 * @file stun.c STUN (RFC3489) Implementation | 2 * @file stun.c STUN (RFC3489) Implementation |
3 * @ingroup core | 3 * @ingroup core |
4 * | 4 * |
5 * gaim | 5 * gaim |
6 * | |
7 * STUN implementation inspired by jstun [http://jstun.javawi.de/] | |
6 * | 8 * |
7 * Gaim is the legal property of its developers, whose names are too numerous | 9 * Gaim is the legal property of its developers, whose names are too numerous |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | 10 * to list here. Please refer to the COPYRIGHT file distributed with this |
9 * source distribution. | 11 * source distribution. |
10 * | 12 * |
43 static gint transid[4]; | 45 static gint transid[4]; |
44 | 46 |
45 static GSList *callbacks = 0; | 47 static GSList *callbacks = 0; |
46 static int fd = -1; | 48 static int fd = -1; |
47 gint incb = -1; | 49 gint incb = -1; |
50 gint timeout = -1; | |
48 | 51 |
49 static void do_callbacks() { | 52 static void do_callbacks() { |
50 while(callbacks) { | 53 while(callbacks) { |
51 StunCallback cb = callbacks->data; | 54 StunCallback cb = callbacks->data; |
52 cb(&nattype); | 55 if(cb) |
56 cb(&nattype); | |
53 callbacks = g_slist_remove(callbacks, cb); | 57 callbacks = g_slist_remove(callbacks, cb); |
54 } | 58 } |
55 } | 59 } |
56 | 60 |
57 static void reply_cb(gpointer data, gint source, GaimInputCondition cond) { | 61 static void reply_cb(gpointer data, gint source, GaimInputCondition cond) { |
58 char buffer[10240]; | 62 char buffer[1024]; |
59 char *tmp; | 63 char *tmp; |
60 int len; | 64 int len; |
61 struct in_addr in; | 65 struct in_addr in; |
62 struct stun_attrib *attrib; | 66 struct stun_attrib *attrib; |
63 struct stun_header *hdr; | 67 struct stun_header *hdr; |
64 struct ifconf ifc; | 68 struct ifconf ifc; |
65 struct ifreq *ifr; | 69 struct ifreq *ifr; |
66 struct sockaddr_in *sinptr; | 70 struct sockaddr_in *sinptr; |
67 | 71 |
68 len = recv(source, buffer, 10240, 0); | 72 len = recv(source, buffer, 1024, 0); |
69 | 73 |
70 hdr = (struct stun_header*)buffer; | 74 hdr = (struct stun_header*)buffer; |
71 if(hdr->transid[0]!=transid[0] || hdr->transid[1]!=transid[1] || hdr->transid[2]!=transid[2] || hdr->transid[3]!=transid[3]) { // wrong transaction | 75 if(hdr->transid[0]!=transid[0] || hdr->transid[1]!=transid[1] || hdr->transid[2]!=transid[2] || hdr->transid[3]!=transid[3]) { // wrong transaction |
72 gaim_debug_info("simple", "got wrong transid\n"); | 76 gaim_debug_info("simple", "got wrong transid\n"); |
73 return; | 77 return; |
110 } | 114 } |
111 } | 115 } |
112 } | 116 } |
113 | 117 |
114 do_callbacks(); | 118 do_callbacks(); |
119 gaim_timeout_remove(timeout); | |
115 gaim_input_remove(incb); | 120 gaim_input_remove(incb); |
116 } | 121 } |
117 | 122 |
123 static gboolean timeoutfunc(void *blah) { | |
124 /* remove input */ | |
125 gaim_input_remove(incb); | |
126 | |
127 /* set unknown */ | |
128 nattype.status = 0; | |
129 | |
130 /* callbacks */ | |
131 do_callbacks(); | |
132 | |
133 return FALSE; | |
134 } | |
135 | |
136 | |
118 struct stun_nattype *gaim_stun_discover(StunCallback cb) { | 137 struct stun_nattype *gaim_stun_discover(StunCallback cb) { |
119 struct sockaddr_in addr; | 138 struct sockaddr_in addr; |
120 struct stun_header data; | 139 struct stun_header data; |
121 int ret = 0; | 140 int ret = 0; |
122 const char *ip = gaim_prefs_get_string("/core/network/stun_ip"); | 141 const char *ip = gaim_prefs_get_string("/core/network/stun_ip"); |
123 int port = gaim_prefs_get_int("/core/network/stun_port"); | 142 int port = gaim_prefs_get_int("/core/network/stun_port"); |
143 | |
144 if(!ip || !port) { | |
145 nattype.status = 0; | |
146 if(cb) cb(&nattype); | |
147 return &nattype; | |
148 } | |
124 | 149 |
125 if(nattype.status == 1) { // currently discovering | 150 if(nattype.status == 1) { // currently discovering |
126 callbacks = g_slist_append(callbacks, cb); | 151 if(cb) callbacks = g_slist_append(callbacks, cb); |
127 return NULL; | 152 return NULL; |
128 } | 153 } |
129 if(nattype.status == 2 || nattype.status == 0) { // already discovered | 154 if(nattype.status != -1) { // already discovered |
130 cb(&nattype); | 155 if(cb) cb(&nattype); |
131 return &nattype; | 156 return &nattype; |
132 } | 157 } |
133 | |
134 if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | 158 if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
135 nattype.status = 0; | 159 nattype.status = 0; |
136 cb(&nattype); | 160 if(cb) cb(&nattype); |
137 return &nattype; | 161 return &nattype; |
138 } | 162 } |
139 | 163 |
140 addr.sin_family = AF_INET; | 164 addr.sin_family = AF_INET; |
141 addr.sin_port = htons(12108); | 165 addr.sin_port = htons(12108); |
143 while( ((ret = bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) < 0 ) && ntohs(addr.sin_port) < 12208) { | 167 while( ((ret = bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) < 0 ) && ntohs(addr.sin_port) < 12208) { |
144 addr.sin_port = htons(ntohs(addr.sin_port)+1); | 168 addr.sin_port = htons(ntohs(addr.sin_port)+1); |
145 } | 169 } |
146 if( ret < 0 ) { | 170 if( ret < 0 ) { |
147 nattype.status = 0; | 171 nattype.status = 0; |
148 cb(&nattype); | 172 if(cb) cb(&nattype); |
149 return &nattype; | 173 return &nattype; |
150 } | 174 } |
151 incb = gaim_input_add(fd, GAIM_INPUT_READ, reply_cb, NULL); | 175 incb = gaim_input_add(fd, GAIM_INPUT_READ, reply_cb, NULL); |
152 | 176 |
153 if(port == 0 || ip == NULL || ip[0] == '\0') return NULL; | 177 if(port == 0 || ip == NULL || ip[0] == '\0') return NULL; |
163 transid[2] = data.transid[2] = rand(); | 187 transid[2] = data.transid[2] = rand(); |
164 transid[3] = data.transid[3] = rand(); | 188 transid[3] = data.transid[3] = rand(); |
165 | 189 |
166 if( sendto(fd, &data, sizeof(struct stun_header), 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < sizeof(struct stun_header)) { | 190 if( sendto(fd, &data, sizeof(struct stun_header), 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < sizeof(struct stun_header)) { |
167 nattype.status = 0; | 191 nattype.status = 0; |
168 cb(&nattype); | 192 if(cb) cb(&nattype); |
169 return &nattype; | 193 return &nattype; |
170 } | 194 } |
195 if(cb) callbacks = g_slist_append(callbacks, cb); | |
196 timeout = gaim_timeout_add(2000, (GSourceFunc)timeoutfunc, NULL); | |
171 return NULL; | 197 return NULL; |
172 } | 198 } |