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,