Mercurial > pidgin
comparison src/protocols/oscar/oscar.c @ 8983:460d02fe03df
[gaim-migrate @ 9758]
This makes us tell the other person to connect to us if we can't connect
to them, for direct im. Also I made us used the clientip instead of the
verified ip for direct im, because I get the impression that's what the
official aim clients use, and I think it sort of makes sense.
Maybe I should compare the two and not bother trying if they're different.
committer: Tailor Script <tailor@pidgin.im>
author | Tim Ringenbach <marv@pidgin.im> |
---|---|
date | Thu, 20 May 2004 02:03:34 +0000 |
parents | a4fd6666bb83 |
children | 4623d24347d8 |
comparison
equal
deleted
inserted
replaced
8982:a4fd6666bb83 | 8983:460d02fe03df |
---|---|
286 /* for icons */ | 286 /* for icons */ |
287 static gboolean gaim_icon_timerfunc(gpointer data); | 287 static gboolean gaim_icon_timerfunc(gpointer data); |
288 | 288 |
289 /* just because */ | 289 /* just because */ |
290 static void oscar_callback(gpointer data, gint source, GaimInputCondition condition); | 290 static void oscar_callback(gpointer data, gint source, GaimInputCondition condition); |
291 static void oscar_direct_im_initiate(GaimConnection *gc, const char *who, const char *cookie); | |
291 | 292 |
292 /* remove these at some point? */ | 293 /* remove these at some point? */ |
293 /* Because I don't like forward declarations? I think that was why... */ | 294 /* Because I don't like forward declarations? I think that was why... */ |
294 static void oscar_set_info(GaimConnection *gc, const char *text); | 295 static void oscar_set_info(GaimConnection *gc, const char *text); |
295 static void oscar_set_away(GaimConnection *gc, const char *state, const char *message); | 296 static void oscar_set_away(GaimConnection *gc, const char *state, const char *message); |
793 oscar_direct_im_destroy(od, dim); | 794 oscar_direct_im_destroy(od, dim); |
794 return; | 795 return; |
795 } | 796 } |
796 | 797 |
797 if (source < 0) { | 798 if (source < 0) { |
798 oscar_direct_im_disconnect(od, dim); | 799 fu8_t cookie[8]; |
800 char *who = g_strdup(dim->name); | |
801 const char *tmp = aim_odc_getcookie(dim->conn); | |
802 | |
803 memcpy(cookie, tmp, 8); | |
804 oscar_direct_im_destroy(od, dim); | |
805 oscar_direct_im_initiate(gc, who, cookie); | |
806 gaim_debug_info("oscar", "asking direct im initiator to connect to us\n"); | |
807 g_free(who); | |
799 return; | 808 return; |
800 } | 809 } |
801 | 810 |
802 dim->conn->fd = source; | 811 dim->conn->fd = source; |
803 aim_conn_completeconnect(od->sess, dim->conn); | 812 aim_conn_completeconnect(od->sess, dim->conn); |
804 conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, dim->name); | 813 conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, dim->name); |
805 | 814 |
806 /* This is the best way to see if we're connected or not */ | 815 /* This is the best way to see if we're connected or not */ |
816 /* Is this really needed? */ | |
807 if (getpeername(source, &name, &name_len) == 0) { | 817 if (getpeername(source, &name, &name_len) == 0) { |
808 g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name); | 818 g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name); |
809 dim->connected = TRUE; | 819 dim->connected = TRUE; |
810 gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); | 820 gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); |
811 } | 821 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, oscar_callback, dim->conn); |
812 | 822 } else { |
813 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, oscar_callback, dim->conn); | 823 fu8_t cookie[8]; |
824 char *who = g_strdup(dim->name); | |
825 const char *tmp = aim_odc_getcookie(dim->conn); | |
826 | |
827 memcpy(cookie, tmp, 8); | |
828 oscar_direct_im_destroy(od, dim); | |
829 oscar_direct_im_initiate(gc, who, cookie); | |
830 gaim_debug_info("oscar", "asking direct im initiator to connect to us\n"); | |
831 g_free(who); | |
832 return; | |
833 } | |
834 | |
835 | |
814 } | 836 } |
815 | 837 |
816 static void accept_direct_im_request(struct ask_direct *d) { | 838 static void accept_direct_im_request(struct ask_direct *d) { |
817 GaimConnection *gc = d->gc; | 839 GaimConnection *gc = d->gc; |
818 OscarData *od; | 840 OscarData *od; |
870 conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, d->sn); | 892 conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, d->sn); |
871 tmp = g_strdup_printf(_("Attempting to connect to %s at %s:%hu for Direct IM."), d->sn, host, | 893 tmp = g_strdup_printf(_("Attempting to connect to %s at %s:%hu for Direct IM."), d->sn, host, |
872 port); | 894 port); |
873 gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | 895 gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); |
874 g_free(tmp); | 896 g_free(tmp); |
875 | 897 |
876 g_free(host); | 898 g_free(host); |
877 if (rc < 0) { | 899 if (rc < 0) { |
878 dim->gpc_pend = FALSE; | 900 dim->gpc_pend = FALSE; |
879 oscar_direct_im_disconnect(od, dim); | 901 oscar_direct_im_disconnect(od, dim); |
880 destroy_direct_im_request(d); | 902 destroy_direct_im_request(d); |
1235 static void oscar_cancel_direct_im(struct ask_do_dir_im *data) { | 1257 static void oscar_cancel_direct_im(struct ask_do_dir_im *data) { |
1236 g_free(data->who); | 1258 g_free(data->who); |
1237 g_free(data); | 1259 g_free(data); |
1238 } | 1260 } |
1239 | 1261 |
1240 static void oscar_direct_im(struct ask_do_dir_im *data) { | 1262 /* this function is used to initiate a direct im session with someone. |
1241 GaimConnection *gc = data->gc; | 1263 * we start listening on a port and send a request. they either connect |
1264 * or send some kind of reply. If they can't connect, they ask us to | |
1265 * connect to them, and so we do that. | |
1266 * | |
1267 * this function will also get called if the other side initiate's a direct | |
1268 * im and we try to connect and fail. in that case cookie will not be null. | |
1269 * | |
1270 * note that cookie is an 8 byte string that isn't NULL terminated | |
1271 */ | |
1272 static void oscar_direct_im_initiate(GaimConnection *gc, const char *who, const char *cookie) { | |
1242 OscarData *od; | 1273 OscarData *od; |
1243 struct oscar_direct_im *dim; | 1274 struct oscar_direct_im *dim; |
1244 int listenfd; | 1275 int listenfd; |
1245 const char *ip; | 1276 const char *ip; |
1246 | 1277 |
1247 if (!g_list_find(gaim_connections_get_all(), gc)) { | |
1248 g_free(data->who); | |
1249 g_free(data); | |
1250 return; | |
1251 } | |
1252 | |
1253 od = (OscarData *)gc->proto_data; | 1278 od = (OscarData *)gc->proto_data; |
1254 | 1279 |
1255 dim = oscar_direct_im_find(od, data->who); | 1280 dim = oscar_direct_im_find(od, who); |
1256 if (dim) { | 1281 if (dim) { |
1257 if (!(dim->connected)) { /* We'll free the old, unconnected dim, and start over */ | 1282 if (!(dim->connected)) { /* We'll free the old, unconnected dim, and start over */ |
1258 oscar_direct_im_disconnect(od, dim); | 1283 oscar_direct_im_disconnect(od, dim); |
1259 gaim_debug_info("oscar", | 1284 gaim_debug_info("oscar", |
1260 "Gave up on old direct IM, trying again\n"); | 1285 "Gave up on old direct IM, trying again\n"); |
1261 } else { | 1286 } else { |
1262 gaim_notify_error(gc, NULL, "DirectIM already open.", NULL); | 1287 gaim_notify_error(gc, NULL, "DirectIM already open.", NULL); |
1263 g_free(data->who); | |
1264 g_free(data); | |
1265 return; | 1288 return; |
1266 } | 1289 } |
1267 } | 1290 } |
1268 dim = g_new0(struct oscar_direct_im, 1); | 1291 dim = g_new0(struct oscar_direct_im, 1); |
1269 dim->gc = gc; | 1292 dim->gc = gc; |
1270 g_snprintf(dim->name, sizeof dim->name, "%s", data->who); | 1293 g_snprintf(dim->name, sizeof dim->name, "%s", who); |
1271 | 1294 |
1272 listenfd = gaim_network_listen_range(5190, 5199); | 1295 listenfd = gaim_network_listen_range(5190, 5199); |
1273 ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1); | 1296 ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1); |
1274 dim->conn = aim_odc_initiate(od->sess, data->who, listenfd, gaim_network_ip_atoi(ip), gaim_network_get_port_from_fd(listenfd), NULL); | 1297 dim->conn = aim_odc_initiate(od->sess, who, listenfd, gaim_network_ip_atoi(ip), gaim_network_get_port_from_fd(listenfd), cookie); |
1275 if (dim->conn != NULL) { | 1298 if (dim->conn != NULL) { |
1276 char *tmp; | 1299 char *tmp; |
1277 GaimConversation *conv; | 1300 GaimConversation *conv; |
1278 | 1301 |
1279 od->direct_ims = g_slist_append(od->direct_ims, dim); | 1302 od->direct_ims = g_slist_append(od->direct_ims, dim); |
1280 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, | 1303 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, |
1281 oscar_callback, dim->conn); | 1304 oscar_callback, dim->conn); |
1282 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIM_ESTABLISHED, | 1305 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIM_ESTABLISHED, |
1283 gaim_odc_initiate, 0); | 1306 gaim_odc_initiate, 0); |
1284 | 1307 |
1285 conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, data->who); | 1308 conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, who); |
1286 tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for Direct IM."), data->who, ip, | 1309 tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for Direct IM."), who, ip, |
1287 gaim_network_get_port_from_fd(listenfd)); | 1310 gaim_network_get_port_from_fd(listenfd)); |
1288 gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | 1311 gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); |
1289 g_free(tmp); | 1312 g_free(tmp); |
1290 } else { | 1313 } else { |
1291 gaim_notify_error(gc, NULL, _("Unable to open Direct IM"), NULL); | 1314 gaim_notify_error(gc, NULL, _("Unable to open Direct IM"), NULL); |
1292 oscar_direct_im_destroy(od, dim); | 1315 oscar_direct_im_destroy(od, dim); |
1293 } | 1316 } |
1294 | 1317 } |
1318 | |
1319 static void oscar_direct_im(struct ask_do_dir_im *data) { | |
1320 GaimConnection *gc = data->gc; | |
1321 | |
1322 if (!g_list_find(gaim_connections_get_all(), gc)) { | |
1323 g_free(data->who); | |
1324 g_free(data); | |
1325 return; | |
1326 } | |
1327 | |
1328 oscar_direct_im_initiate(gc, data->who, NULL); | |
1295 g_free(data->who); | 1329 g_free(data->who); |
1296 g_free(data); | 1330 g_free(data); |
1297 } | 1331 } |
1298 | 1332 |
1299 /* this is the right click menu cb thingy */ | 1333 /* this is the right click menu cb thingy */ |
3182 struct ask_direct *d = g_new0(struct ask_direct, 1); | 3216 struct ask_direct *d = g_new0(struct ask_direct, 1); |
3183 struct oscar_direct_im *dim = oscar_direct_im_find(od, userinfo->sn); | 3217 struct oscar_direct_im *dim = oscar_direct_im_find(od, userinfo->sn); |
3184 char buf[256]; | 3218 char buf[256]; |
3185 | 3219 |
3186 if (!args->verifiedip) { | 3220 if (!args->verifiedip) { |
3221 /* TODO: do something about this, after figuring out what it means */ | |
3187 gaim_debug_info("oscar", | 3222 gaim_debug_info("oscar", |
3188 "directim kill blocked (%s)\n", userinfo->sn); | 3223 "directim kill blocked (%s)\n", userinfo->sn); |
3189 return 1; | 3224 return 1; |
3190 } | 3225 } |
3191 | 3226 |
3192 gaim_debug_info("oscar", | 3227 gaim_debug_info("oscar", |
3193 "%s received direct im request from %s (%s)\n", | 3228 "%s received direct im request from %s (%s)\n", |
3194 username, userinfo->sn, args->verifiedip); | 3229 username, userinfo->sn, args->clientip); |
3195 | 3230 |
3196 d->gc = gc; | 3231 d->gc = gc; |
3197 d->sn = g_strdup(userinfo->sn); | 3232 d->sn = g_strdup(userinfo->sn); |
3198 snprintf(d->ip, sizeof(d->ip), "%s:%d", args->verifiedip, args->port?args->port:5190); | 3233 /* Let's use the clientip here, because I think that's what AIM does. |
3234 * Besides, if the clientip is wrong, we'll probably timeout faster, | |
3235 * and then ask them to connect to us. */ | |
3236 snprintf(d->ip, sizeof(d->ip), "%s:%d", args->clientip, args->port?args->port:5190); | |
3199 memcpy(d->cookie, args->cookie, 8); | 3237 memcpy(d->cookie, args->cookie, 8); |
3200 if (dim && !dim->connected) { | 3238 if (dim && !dim->connected && (!memcmp(aim_odc_getcookie(dim->conn), args->cookie, 8))) { |
3201 oscar_direct_im_destroy(od, dim); | 3239 oscar_direct_im_destroy(od, dim); |
3202 accept_direct_im_request(d); | 3240 accept_direct_im_request(d); |
3203 } else { | 3241 } else { |
3204 if (dim) | 3242 if (dim && !dim->connected) |
3205 gaim_debug_warning("oscar", "DirectIM: received direct im request while " | 3243 gaim_debug_warning("oscar", "DirectIM: received direct im request while " |
3206 "already connected to that buddy!"); | 3244 "already connected to that buddy!"); |
3207 g_snprintf(buf, sizeof buf, _("%s has just asked to directly connect to %s"), userinfo->sn, username); | 3245 g_snprintf(buf, sizeof buf, _("%s has just asked to directly connect to %s"), userinfo->sn, username); |
3208 | 3246 |
3209 gaim_request_action(gc, NULL, buf, | 3247 gaim_request_action(gc, NULL, buf, |