/** * 给好友发送消息. * @param sock udp socket * @param pal class PalInfo * @param msg 消息数据 */ void Command::SendMessage(int sock, PalInfo *pal, const char *msg) { struct sockaddr_in addr; uint32_t packetno; uint8_t count; pal->rpacketn = packetno = packetn; //此数据包需要检验回复 CreateCommand(IPMSG_SENDCHECKOPT | IPMSG_SENDMSG, msg); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; count = 0; do { sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); g_usleep(1000000); count++; } while (pal->rpacketn == packetno && count < MAX_RETRYTIMES); if (pal->rpacketn == packetno) FeedbackError(pal, GROUP_BELONG_TYPE_REGULAR, _("Your pal didn't receive the packet. " "He or she is offline maybe.")); }
/** * 好友更改个人信息. */ void UdpData::SomeoneAbsence() { PalInfo *pal; const char *ptr; /* 若好友不兼容iptux协议,则需转码 */ pal = cthrd.GetPalFromList(ipv4); //利用好友链表只增不减的特性,无须加锁 ptr = iptux_skip_string(buf, size, 3); if (!ptr || *ptr == '\0') ConvertEncode(pal ? pal->encode : progdt.encode); /* 加入或更新好友列表 */ gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); if (pal) { UpdatePalInfo(pal); cthrd.UpdatePalToList(ipv4); } else { pal = CreatePalInfo(); cthrd.AttachPalToList(pal); } pthread_mutex_unlock(cthrd.GetMutex()); if (mwin.PaltreeContainItem(ipv4)) mwin.UpdateItemToPaltree(ipv4); else mwin.AttachItemToPaltree(ipv4); gdk_threads_leave(); }
/** * 好友发送个性签名. */ void UdpData::SomeoneSendSign() { PalInfo *pal; char *sign; if (!(pal = cthrd.GetPalFromList(ipv4))) return; /* 若好友不兼容iptux协议,则需转码 */ if (!FLAG_ISSET(pal->flags, 0)) ConvertEncode(pal->encode); /* 对编码作适当调整 */ if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) { g_free(pal->encode); pal->encode = g_strdup(encode ? encode : "utf-8"); } /* 更新 */ if ( (sign = ipmsg_get_attach(buf, ':', 5))) { g_free(pal->sign); pal->sign = sign; gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); cthrd.UpdatePalToList(ipv4); pthread_mutex_unlock(cthrd.GetMutex()); mwin.UpdateItemToPaltree(ipv4); gdk_threads_leave(); } }
/** * 向好友请求文件数据. * @param sock tcp socket * @param pal class PalInfo * @param packetno 好友消息的包编号 * @param fileid 文件ID标识 * @param offset 文件偏移量 * @return 消息发送成功与否 */ bool Command::SendAskData(int sock, PalInfo *pal, uint32_t packetno, uint32_t fileid, int64_t offset) { char attrstr[35]; //8+1+8+1+16 +1 =35 struct sockaddr_in addr; char *iptuxstr = "iptux"; snprintf(attrstr, 35, "%" PRIx32 ":%" PRIx32 ":%" PRIx64, packetno, fileid, offset); //IPMSG和Feiq的命令字段都是只有IPMSG_GETFILEDATA,使用(IPMSG_FILEATTACHOPT | IPMSG_GETFILEDATA) //会产生一些潜在的不兼容问题,所以在发往非iptux时只使用IPMSG_GETFILEDATA if(strstr(pal->version,iptuxstr)) CreateCommand(IPMSG_FILEATTACHOPT | IPMSG_GETFILEDATA, attrstr); else CreateCommand(IPMSG_GETFILEDATA, attrstr); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; if (((connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) && (errno != EINTR)) || (xwrite(sock, buf, size) == -1)) return false; return true; }
/** * 好友上线. */ void UdpData::SomeoneEntry() { Command cmd; pthread_t pid; PalInfo *pal; /* 转换缓冲区数据编码 */ ConvertEncode(progdt.encode); /* 加入或更新好友列表 */ gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); if ( (pal = cthrd.GetPalFromList(ipv4))) { UpdatePalInfo(pal); cthrd.UpdatePalToList(ipv4); } else { pal = CreatePalInfo(); cthrd.AttachPalToList(pal); } pthread_mutex_unlock(cthrd.GetMutex()); if (mwin.PaltreeContainItem(ipv4)) mwin.UpdateItemToPaltree(ipv4); else mwin.AttachItemToPaltree(ipv4); gdk_threads_leave(); /* 通知好友本大爷在线 */ cmd.SendAnsentry(cthrd.UdpSockQuote(), pal); if (FLAG_ISSET(pal->flags, 0)) { pthread_create(&pid, NULL, ThreadFunc(CoreThread::SendFeatureData), pal); pthread_detach(pid); } }
/** * 发送本人的签名信息. * @param sock udp socket * @param pal class PalInfo */ void Command::SendMySign(int sock, PalInfo *pal) { struct sockaddr_in addr; CreateCommand(IPTUX_SENDSIGN, progdt.sign); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); }
/** * 向好友请求共享文件信息. * @param sock udp socket * @param pal class PalInfo * @param opttype 命令额外选项 * @param attach 附加数据,即密码 */ void Command::SendAskShared(int sock, PalInfo *pal, uint32_t opttype, const char *attach) { struct sockaddr_in addr; CreateCommand(opttype | IPTUX_ASKSHARED, attach); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); }
/** * 群发消息(被其他函数调用). * @param sock udp socket * @param pal class PalInfo * @param msg 消息数据 */ void Command::SendGroupMsg(int sock, PalInfo *pal, const char *msg) { struct sockaddr_in addr; CreateCommand(IPMSG_BROADCASTOPT | IPMSG_SENDMSG, msg); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); }
/** * 通告好友本人下线. * @param sock udp socket * @param pal class PalInfo */ void Command::SendExit(int sock, PalInfo *pal) { struct sockaddr_in addr; CreateCommand(IPMSG_DIALUPOPT | IPMSG_BR_EXIT, NULL); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); }
/** * 通告好友本人个人信息已变. * @param sock udp socket * @param pal class PalInfo */ void Command::SendAbsence(int sock, PalInfo *pal) { struct sockaddr_in addr; CreateCommand(IPMSG_ABSENCEOPT | IPMSG_BR_ABSENCE, progdt.nickname); ConvertEncode(pal->encode); CreateIptuxExtra(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); }
/** * 向好友发送文件信息. * @param sock udp socket * @param pal class PalInfo * @param opttype 命令额外选项 * @param extra 扩展数据,即文件信息 */ void Command::SendFileInfo(int sock, PalInfo *pal, uint32_t opttype, const char *extra) { struct sockaddr_in addr; CreateCommand(opttype | IPMSG_FILEATTACHOPT | IPMSG_SENDMSG, NULL); ConvertEncode(pal->encode); CreateIpmsgExtra(extra, pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); }
/** * 回复已收到消息. * @param sock udp socket * @param pal class PalInfo * @param packetno 好友消息的包编号 */ void Command::SendReply(int sock, PalInfo *pal, uint32_t packetno) { char packetstr[11]; //10 +1 =11 struct sockaddr_in addr; snprintf(packetstr, 11, "%" PRIu32, packetno); CreateCommand(IPMSG_SENDCHECKOPT | IPMSG_RECVMSG, packetstr); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); }
/** * 尝试着给某计算机发送一个上线信息数据包. * @param sock udp socket * @param ipv4 ipv4 address */ void Command::SendDetectPacket(int sock, in_addr_t ipv4) { struct sockaddr_in addr; CreateCommand(IPMSG_DIALUPOPT | IPMSG_ABSENCEOPT | IPMSG_BR_ENTRY, progdt.nickname); ConvertEncode(progdt.encode); CreateIptuxExtra(progdt.encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = ipv4; sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); }
/** * 向局域网某些计算机单独发送上线信息. * @param sock udp socket */ void Command::DialUp(int sock) { struct sockaddr_in addr; in_addr_t startip, endip, ipv4; NetSegment *pns; GSList *list, *tlist; CreateCommand(IPMSG_DIALUPOPT | IPMSG_ABSENCEOPT | IPMSG_BR_ENTRY, progdt.nickname); ConvertEncode(progdt.encode); CreateIptuxExtra(progdt.encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); //与某些代码片段的获取网段描述相冲突,必须复制出来使用 pthread_mutex_lock(&progdt.mutex); list = progdt.CopyNetSegment(); pthread_mutex_unlock(&progdt.mutex); tlist = list; while (tlist) { pns = (NetSegment *)tlist->data; inet_pton(AF_INET, pns->startip, &startip); startip = ntohl(startip); inet_pton(AF_INET, pns->endip, &endip); endip = ntohl(endip); ipv4_order(&startip, &endip); ipv4 = startip; while (ipv4 <= endip) { addr.sin_addr.s_addr = htonl(ipv4); sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); g_usleep(999); ipv4++; } tlist = g_slist_next(tlist); } for (tlist = list; tlist; tlist = g_slist_next(tlist)) delete (NetSegment *)tlist->data; g_slist_free(list); }
/** * 向好友请求目录文件. * @param sock tcp socket * @param pal class PalInfo * @param packetno 好友消息的包编号 * @param fileid 文件ID标识 * @return 消息发送成功与否 */ bool Command::SendAskFiles(int sock, PalInfo *pal, uint32_t packetno, uint32_t fileid) { char attrstr[20]; //8+1+8+1+1 +1 =20 struct sockaddr_in addr; snprintf(attrstr, 20, "%" PRIx32 ":%" PRIx32 ":0", packetno, fileid); //兼容LanQQ软件 CreateCommand(IPMSG_FILEATTACHOPT | IPMSG_GETDIRFILES, attrstr); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; if (((connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) && (errno != EINTR)) || (xwrite(sock, buf, size) == -1)) return false; return true; }
/** * 向局域网所有计算机广播上线信息. * @param sock udp socket */ void Command::BroadCast(int sock) { struct sockaddr_in addr; GSList *list, *tlist; CreateCommand(IPMSG_ABSENCEOPT | IPMSG_BR_ENTRY, progdt.nickname); ConvertEncode(progdt.encode); CreateIptuxExtra(progdt.encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); tlist = list = get_sys_broadcast_addr(sock); while (tlist) { addr.sin_addr.s_addr = GPOINTER_TO_UINT(tlist->data); sendto(sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)); g_usleep(9999); tlist = g_slist_next(tlist); } g_slist_free(list); }
/** * 发送底层数据(即发送为最终用户所不能察觉的文件数据). * @param sock tcp socket * @param pal class PalInfo * @param opttype 命令额外选项 * @param path 文件路径 */ void Command::SendSublayer(int sock, PalInfo *pal, uint32_t opttype, const char *path) { struct sockaddr_in addr; int fd; CreateCommand(opttype | IPTUX_SENDSUBLAYER, NULL); ConvertEncode(pal->encode); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(IPTUX_DEFAULT_PORT); addr.sin_addr.s_addr = pal->ipv4; if (((connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) && (errno != EINTR)) || (xwrite(sock, buf, size) == -1) || ((fd = open(path, O_RDONLY)) == -1)) return; SendSublayerData(sock, fd); close(fd); }
nsresult nsTestUConv::Encode(PRUnichar ** aSrc, PRUnichar * aSrcEnd, char ** aDest, char * aDestEnd, const nsAFlatCString& aCharset) { char * trace = "Encode"; mLog.AddTrace(trace); nsresult res = NS_OK; nsCOMPtr<nsICharsetConverterManager> ccMan = do_GetService(kCharsetConverterManagerCID, &res); if (NS_FAILED(res)) { mLog.PrintError("NS_WITH_SERVICE", res); return res; } nsCOMPtr<nsIUnicodeEncoder> enc; res = ccMan->GetUnicodeEncoder(aCharset.get(), getter_AddRefs(enc)); if (NS_FAILED(res)) { mLog.PrintError("GetUnicodeEncoder()", res); return res; } res = ConvertEncode(aSrc, aSrcEnd, aDest, aDestEnd, enc); if (NS_FAILED(res)) { mLog.PrintError("Convert()", res); return res; } res = FinishEncode(aDest, aDestEnd, enc); if (NS_FAILED(res)) { mLog.PrintError("Finish()", res); return res; } mLog.DelTrace(trace); return res; }
/** * 好友在线. */ void UdpData::SomeoneAnsentry() { Command cmd; pthread_t pid; PalInfo *pal; const char *ptr; /* 若好友不兼容iptux协议,则需转码 */ ptr = iptux_skip_string(buf, size, 3); if (!ptr || *ptr == '\0') ConvertEncode(progdt.encode); /* 加入或更新好友列表 */ gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); if ( (pal = cthrd.GetPalFromList(ipv4))) { UpdatePalInfo(pal); cthrd.UpdatePalToList(ipv4); } else { pal = CreatePalInfo(); cthrd.AttachPalToList(pal); } pthread_mutex_unlock(cthrd.GetMutex()); if (mwin.PaltreeContainItem(ipv4)) mwin.UpdateItemToPaltree(ipv4); else mwin.AttachItemToPaltree(ipv4); gdk_threads_leave(); /* 更新本大爷的数据信息 */ if (FLAG_ISSET(pal->flags, 0)) { pthread_create(&pid, NULL, ThreadFunc(CoreThread::SendFeatureData), pal); pthread_detach(pid); } else if (strcasecmp(progdt.encode, pal->encode) != 0) cmd.SendAnsentry(cthrd.UdpSockQuote(), pal); }
/** * 好友广播消息. */ void UdpData::SomeoneBcstmsg() { GroupInfo *grpinf; PalInfo *pal; uint32_t commandno, packetno; char *text; /* 如果对方兼容iptux协议,则无须再转换编码 */ pal = cthrd.GetPalFromList(ipv4); if (!pal || !FLAG_ISSET(pal->flags, 0)) ConvertEncode(pal ? pal->encode : progdt.encode); /* 确保好友在线,并对编码作出适当调整 */ pal = AssertPalOnline(); if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) { g_free(pal->encode); pal->encode = g_strdup(encode ? encode : "utf-8"); } /* 检查此消息是否过时 */ packetno = iptux_get_dec_number(buf, ':', 1); if (packetno <= pal->packetn) return; pal->packetn = packetno; /* 插入消息&在消息队列中注册 */ text = ipmsg_get_attach(buf, ':', 5); if (text && *text != '\0') { commandno = iptux_get_dec_number(buf, ':', 4); /*/* 插入消息 */ switch (GET_OPT(commandno)) { case IPTUX_BROADCASTOPT: InsertMessage(pal, GROUP_BELONG_TYPE_BROADCAST, text); break; case IPTUX_GROUPOPT: InsertMessage(pal, GROUP_BELONG_TYPE_GROUP, text); break; case IPTUX_SEGMENTOPT: InsertMessage(pal, GROUP_BELONG_TYPE_SEGMENT, text); break; case IPTUX_REGULAROPT: default: InsertMessage(pal, GROUP_BELONG_TYPE_REGULAR, text); break; } /*/* 注册消息 */ pthread_mutex_lock(cthrd.GetMutex()); switch (GET_OPT(commandno)) { case IPTUX_BROADCASTOPT: grpinf = cthrd.GetPalBroadcastItem(pal); break; case IPTUX_GROUPOPT: grpinf = cthrd.GetPalGroupItem(pal); break; case IPTUX_SEGMENTOPT: grpinf = cthrd.GetPalSegmentItem(pal); break; case IPTUX_REGULAROPT: default: grpinf = cthrd.GetPalRegularItem(pal); break; } if (!grpinf->dialog && !cthrd.MsglineContainItem(grpinf)) cthrd.PushItemToMsgline(grpinf); pthread_mutex_unlock(cthrd.GetMutex()); } g_free(text); /* 播放提示音 */ if (FLAG_ISSET(progdt.sndfgs, 1)) sndsys.Playing(progdt.msgtip); }
/** * 好友发送消息. * */ void UdpData::SomeoneSendmsg() { GroupInfo *grpinf; PalInfo *pal; Command cmd; uint32_t commandno, packetno; char *text; pthread_t pid; DialogPeer *dlgpr; GtkWidget *window; /* 如果对方兼容iptux协议,则无须再转换编码 */ pal = cthrd.GetPalFromList(ipv4); if (!pal || !FLAG_ISSET(pal->flags, 0)) ConvertEncode(pal ? pal->encode : progdt.encode); /* 确保好友在线,并对编码作出适当调整 */ pal = AssertPalOnline(); if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) { g_free(pal->encode); pal->encode = g_strdup(encode ? encode : "utf-8"); } /* 回复好友并检查此消息是否过时 */ commandno = iptux_get_dec_number(buf, ':', 4); packetno = iptux_get_dec_number(buf, ':', 1); if (commandno & IPMSG_SENDCHECKOPT) cmd.SendReply(cthrd.UdpSockQuote(), pal, packetno); if (packetno <= pal->packetn) return; pal->packetn = packetno; /* 插入消息&在消息队列中注册 */ text = ipmsg_get_attach(buf, ':', 5); if (text && *text != '\0') { /*/* 插入消息 */ // if ((commandno & IPMSG_BROADCASTOPT) || (commandno & IPMSG_MULTICASTOPT)) // InsertMessage(pal, GROUP_BELONG_TYPE_BROADCAST, text); // else InsertMessage(pal, GROUP_BELONG_TYPE_REGULAR, text); } g_free(text); /*/* 注册消息 */ pthread_mutex_lock(cthrd.GetMutex()); // if ((commandno & IPMSG_BROADCASTOPT) || (commandno & IPMSG_MULTICASTOPT)) // grpinf = cthrd.GetPalBroadcastItem(pal); // else grpinf = cthrd.GetPalRegularItem(pal); if (!grpinf->dialog && !cthrd.MsglineContainItem(grpinf)) cthrd.PushItemToMsgline(grpinf); pthread_mutex_unlock(cthrd.GetMutex()); /* 标记位处理 先处理底层数据,后面显示窗口*/ if (commandno & IPMSG_FILEATTACHOPT) { if ((commandno & IPTUX_SHAREDOPT) && (commandno & IPTUX_PASSWDOPT)) { pthread_create(&pid, NULL, ThreadFunc(ThreadAskSharedPasswd), pal); pthread_detach(pid); } else RecvPalFile(); } window = GTK_WIDGET(grpinf->dialog); //这里不知道为什么运行时一直会提示window不是object dlgpr = (DialogPeer *)(g_object_get_data(G_OBJECT(window),"dialog")); if(grpinf->dialog) dlgpr->ShowDialogPeer(dlgpr); /* 是否直接弹出聊天窗口 */ if (FLAG_ISSET(progdt.flags, 7)) { gdk_threads_enter(); if (!(grpinf->dialog)) { // switch (grpinf->type) { // case GROUP_BELONG_TYPE_REGULAR: DialogPeer::PeerDialogEntry(grpinf); // break; // case GROUP_BELONG_TYPE_SEGMENT: // case GROUP_BELONG_TYPE_GROUP: // case GROUP_BELONG_TYPE_BROADCAST: // DialogGroup::GroupDialogEntry(grpinf); // default: // break; // } } else { gtk_window_present(GTK_WINDOW(grpinf->dialog)); } gdk_threads_leave(); } /* 播放提示音 */ if (FLAG_ISSET(progdt.sndfgs, 1)) sndsys.Playing(progdt.msgtip); }