/* Tlen Protocol Plugin for Miranda NG Copyright (C) 2004-2007 Piotr Piastucki This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "tlen_p2p_old.h" #include #include #include #include #include "tlen_list.h" static void logInfo(const char *filename, const char *fmt, ...) { SYSTEMTIME time; char *str; va_list vararg; int strsize; FILE *flog=fopen(filename,"at"); if (flog != NULL) { GetLocalTime(&time); va_start(vararg, fmt); str = (char *) mir_alloc(strsize=2048); while (mir_vsnprintf(str, strsize, fmt, vararg) == -1) str = (char *) realloc(str, strsize+=2048); va_end(vararg); fprintf(flog,"%04d-%02d-%02d %02d:%02d:%02d,%03d [%s]",time.wYear,time.wMonth,time.wDay,time.wHour,time.wMinute,time.wSecond,time.wMilliseconds, "INFO"); fprintf(flog," %s\n",str); mir_free(str); fclose(flog); } } void __cdecl TlenNewFileReceiveThread(TLEN_FILE_TRANSFER *ft) { ft->proto->debugLogA("P2P receive thread started"); ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0); // ft->mode = FT_RECV; // ft->currentFile = 0; // ft->state = FT_CONNECTING; { FILE * fout = fopen("tlen_recv.dxx", "wt"); SOCKADDR_IN toad; toad.sin_family = AF_INET; toad.sin_addr.s_addr = inet_addr(ft->hostName); toad.sin_port = htons(ft->wPort); if (fout != NULL) { fprintf(fout, "START:\n"); } if (fout != NULL) { fclose(fout); } while (ft->udps != INVALID_SOCKET) { SOCKADDR_IN cad; int alen; int j, n; unsigned char buff[1024]; alen = sizeof(struct sockaddr); n=recvfrom(ft->udps, (char*)buff,sizeof(buff),0, (struct sockaddr *) &cad, &alen); if (n<0) { break; } logInfo("tlen_recv.dxx", "UDP"); fout = fopen("tlen_recv.dxx", "at"); if (fout != NULL) { fprintf(fout, "\n|RECV %d bytes from %s:%d|",n, inet_ntoa(cad.sin_addr), cad.sin_port); for (j = 0; j < n; j++) { fprintf(fout, "%02X-", buff[j]); } } if (n == 1) { alen = sizeof(struct sockaddr); n = sendto(ft->udps, (char*)buff, n, 0,(struct sockaddr *) &toad, alen); if (fout != NULL) { fprintf(fout, "\n|SEND |"); for (j = 0; j < n; j++) { fprintf(fout, "%02X-", buff[j]); } } } if (fout != NULL) { fprintf(fout, "\n"); fclose(fout); } } } if (ft->udps != INVALID_SOCKET) { closesocket(ft->udps); } TlenListRemove(ft->proto, LIST_FILE, ft->iqId); if (ft->state == FT_DONE) ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0); else { ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0); } ft->proto->debugLogA("P2P receive thread ended"); TlenP2PFreeFileTransfer(ft); } void __cdecl TlenNewFileSendThread(TLEN_FILE_TRANSFER *ft) { ft->proto->debugLogA("P2P send thread started"); // ft->mode = FT_RECV; // ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0); // ft->currentFile = 0; // ft->state = FT_CONNECTING; { FILE * fout = fopen("tlen_send.gxx", "wt"); int step = 0; SOCKADDR_IN toad; toad.sin_family = AF_INET; toad.sin_addr.s_addr = inet_addr(ft->hostName); toad.sin_port = htons(ft->wPort); if (fout != NULL) { fprintf(fout, "START:"); } if (fout != NULL) { fclose(fout); } for (step = 0; step < 10; step ++) { // while (ft->udps != INVALID_SOCKET) { int alen; int j, n; unsigned char buff[1024]; alen = sizeof(struct sockaddr); if (step < 3 || step > 5) { buff[0] = 1; n = 1; } else { buff[0] = '$'; buff[1] = '^'; buff[2] = '&'; buff[3] = '%'; n = 4; } n=sendto(ft->udps, (char*)buff, n, 0, (struct sockaddr *)&toad, alen); logInfo("tlen_send.dxx", "UDP"); if (fout != NULL) { fprintf(fout, "|send: %d %s %d|",n, inet_ntoa(toad.sin_addr), toad.sin_port); for (j = 0; j < n; j++) { fprintf(fout, "%02X-", buff[j]); } } if (fout != NULL) { fprintf(fout, "\n"); fclose(fout); } SleepEx(1000, TRUE); } } ft->proto->debugLogA("P2P send thread ended"); } void TlenBindUDPSocket(TLEN_FILE_TRANSFER *ft) { ft->proto->debugLogA("Binding UDP socket"); ft->udps = socket(PF_INET, SOCK_DGRAM, 0); if (ft->udps != INVALID_SOCKET) { SOCKADDR_IN sin; int len = sizeof(struct sockaddr); memset((char *)&sin,0,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = 0; if (bind(ft->udps, (struct sockaddr *)&sin, sizeof(sin)) >= 0) { if (!getsockname((SOCKET)ft->udps,(SOCKADDR *)&sin,&len)) { struct hostent *hp; char host_name[256]; gethostname(host_name, sizeof(host_name)); hp = gethostbyname(host_name); mir_snprintf(host_name, SIZEOF(host_name), "%u.%u.%u.%u", (unsigned char)hp->h_addr_list[0][0], (unsigned char)hp->h_addr_list[0][1], (unsigned char)hp->h_addr_list[0][2], (unsigned char)hp->h_addr_list[0][3]); ft->wLocalPort = ntohs(sin.sin_port); ft->localName= mir_strdup(host_name); ft->proto->debugLogA("UDP socket bound to %s:%d", ft->localName, ft->wLocalPort); } } } } /* aaa sends a file to bbb: 1) aaa wants to SEND bbb a file A SEND: B RECV: 2) bbb ACCEPTs B SEND: A RECV: 3) aaa tries to establish p2p connection: A SEND: B SEND: 3) bbb sends IP/port details B SEND: */ void __cdecl TlenProcessP2P(XmlNode *node, ThreadData *info) { XmlNode *queryNode; TLEN_LIST_ITEM *item; char *from; if (info == NULL) return; queryNode = TlenXmlGetChild(node, "query"); if ((from=TlenXmlGetAttrValue(node, "from")) != NULL) { XmlNode *fs , *vs, *dcng, *dc; /* file send */ fs = TlenXmlGetChild(queryNode, "fs"); /* voice send */ vs = TlenXmlGetChild(queryNode, "vs"); dcng = TlenXmlGetChild(queryNode, "dcng"); dc = TlenXmlGetChild(queryNode, "dc"); if (fs != NULL) { char *e, *id; /* e - step in the process (starting with 1)*/ /* i - id of the file */ /* s - size of the file */ /* c - number of files */ /* v - ??? */ e = TlenXmlGetAttrValue(fs, "e"); id = TlenXmlGetAttrValue(fs, "i"); if (e != NULL) { if (!strcmp(e, "1")) { char *c, *s; TLEN_FILE_TRANSFER * ft = (TLEN_FILE_TRANSFER *) mir_alloc(sizeof(TLEN_FILE_TRANSFER)); memset(ft, 0, sizeof(TLEN_FILE_TRANSFER)); c = TlenXmlGetAttrValue(fs, "c"); s = TlenXmlGetAttrValue(fs, "s"); ft->jid = mir_strdup(from); ft->proto = info->proto; ft->hContact = TlenHContactFromJID(info->proto, from); ft->iqId = mir_strdup(id); ft->fileTotalSize = atoi(s); ft->newP2P = TRUE; if ((item=TlenListAdd(ft->proto, LIST_FILE, ft->iqId)) != NULL) { char fileInfo[128]; item->ft = ft; mir_snprintf(fileInfo, SIZEOF(fileInfo), "%s file(s), %s bytes", c, s); TCHAR* filenameT = mir_utf8decodeT((char*)fileInfo); PROTORECVFILET pre = {0}; pre.flags = PREF_TCHAR; pre.fileCount = 1; pre.timestamp = time(NULL); pre.tszDescription = filenameT; pre.ptszFiles = &filenameT; pre.lParam = (LPARAM)ft; ft->proto->debugLogA("sending chainrecv"); ProtoChainRecvFile(ft->hContact, &pre); mir_free(filenameT); } } else if (!strcmp(e, "3")) { /* transfer error */ } else if (!strcmp(e, "4")) { /* transfer denied */ } else if (!strcmp(e, "5")) { /* transfer accepted */ if ((item=TlenListGetItemPtr(info->proto, LIST_FILE, id)) != NULL) { item->id2 = mir_strdup("84273372"); item->ft->id2 = mir_strdup("84273372"); TlenSend(info->proto, "", from, item->id2, id); } } } } else if (vs != NULL) { } else if (dcng != NULL) { char *s, *id, *id2; info->proto->debugLogA("DCNG"); s = TlenXmlGetAttrValue(dcng, "s"); id2 = TlenXmlGetAttrValue(dcng, "i"); id = TlenXmlGetAttrValue(dcng, "mi"); if (!strcmp(s, "1")) { /* Keys */ /* n - name (file_send) */ /* k - ??? */ /* v - ??? */ /* s - step */ /* i - id of the file */ /* ck - aes key */ /* ks - key size (in bytes) */ /* iv - aes initial vector */ /* mi - p2p connection id */ char *n, *k, *v, *ck, *iv; n = TlenXmlGetAttrValue(dcng, "n"); k = TlenXmlGetAttrValue(dcng, "k"); v = TlenXmlGetAttrValue(dcng, "v"); ck = TlenXmlGetAttrValue(dcng, "ck"); iv = TlenXmlGetAttrValue(dcng, "iv"); if (!strcmp(n, "file_send")) { if ((item=TlenListGetItemPtr(info->proto, LIST_FILE, id)) != NULL) { item->id2 = mir_strdup(id2); item->ft->id2 = mir_strdup(id2); TlenBindUDPSocket(item->ft); TlenSend(info->proto, "", item->ft->jid, item->ft->localName, item->ft->wLocalPort, item->ft->localName, item->ft->wLocalPort, item->ft->id2); } } } else if (!strcmp(s, "2")) { info->proto->debugLogA("step = 2"); info->proto->debugLogA("%s",from); info->proto->debugLogA("%s",id2); /* IP and port */ if ((item=TlenListFindItemPtrById2(info->proto, LIST_FILE, id2)) != NULL) { item->ft->hostName = mir_strdup(TlenXmlGetAttrValue(dcng, "pa")); item->ft->wPort = atoi(TlenXmlGetAttrValue(dcng, "pp")); TlenBindUDPSocket(item->ft); TlenSend(info->proto, "", item->ft->jid, item->ft->localName, item->ft->wLocalPort, item->ft->localName, item->ft->wLocalPort, item->ft->id2); forkthread((void (__cdecl *)(void*))TlenNewFileReceiveThread, 0, item->ft); forkthread((void (__cdecl *)(void*))TlenNewFileSendThread, 0, item->ft); } } else if (!strcmp(s, "4")) { /* IP and port */ if ((item=TlenListFindItemPtrById2(info->proto, LIST_FILE, id2)) != NULL) { info->proto->debugLogA("step = 4"); item->ft->hostName = mir_strdup(TlenXmlGetAttrValue(dcng, "pa")); item->ft->wPort = atoi(TlenXmlGetAttrValue(dcng, "pp")); forkthread((void (__cdecl *)(void*))TlenNewFileReceiveThread, 0, item->ft); } } } else if (dc != NULL) { } } }