void __cdecl KeepAliveThread(LPVOID param) { CSametimeProto* proto = (CSametimeProto*)param; int i = 120; proto->debugLog(_T("KeepAliveThread() start")); while (1) { if (i <= 0) { i = 120; // send keepalive every 120 * 250 = 30000[ms] if (mwSession_isStarted(proto->session) && proto->session) { mwSession_sendKeepalive(proto->session); } } i--; SleepEx(250, TRUE); EnterCriticalSection(&(proto->session_cs)); if (Miranda_Terminated() || !proto->session) { LeaveCriticalSection(&(proto->session_cs)); proto->debugLog(_T("KeepAliveThread() end")); break; } LeaveCriticalSection(&(proto->session_cs)); } return; }
void mwServiceConf_on_invited(mwConference* conf, mwLoginInfo* inviter, const char* invite) { GList *members, *mem; CSametimeProto* proto = getProtoFromMwConference(conf); proto->debugLog(_T("mwServiceConf_on_invited() start")); members = mem = mwConference_getMembers(conf); for (;mem;mem=mem->next) { if (proto->my_login_info && strcmp(proto->my_login_info->login_id, ((mwLoginInfo*)mem->data)->login_id) == 0) { proto->debugLog(_T("mwServiceConf_on_invited() already present")); char* utfs = mir_utf8encodeT(TranslateT("Invitation rejected - already present.")); mwConference_reject(conf, 0, utfs); mir_free(utfs); return; } } g_list_free(members); wchar_t ws_username[128]; MultiByteToWideChar(CP_UTF8, 0, (const char*)inviter->user_name, -1, ws_username, 128); wchar_t ws_invite[512]; MultiByteToWideChar(CP_UTF8, 0, (const char*)invite, -1, ws_invite, 128); if (MessageBoxW(0, ws_invite, ws_username, MB_OKCANCEL) == IDOK) { proto->debugLog(_T("mwServiceConf_on_invited() mwConference_accept")); mwConference_accept(conf); } else { proto->debugLog(_T("mwServiceConf_on_invited() mwConference_reject")); char* temp = mir_utf8encodeT(TranslateT("Your invitation has been rejected.")); mwConference_reject(conf, 0, temp); mir_free(temp); } }
void __cdecl SessionStateChange(mwSession* session, mwSessionState state, gpointer info) { CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR"); proto->debugLog(_T("SessionStateChange() state=[%d]"), state); switch (state) { case mwSession_STARTING: break; case mwSession_HANDSHAKE: break; case mwSession_HANDSHAKE_ACK: break; case mwSession_STARTED: proto->SessionStarted(); break; case mwSession_STOPPING: if ((int)info) {// & ERR_FAILURE) { char *msg = mwError((int)info); TCHAR *msgT = mir_utf8decodeT(msg); proto->showPopup(TranslateTS(msgT), SAMETIME_POPUP_ERROR); mir_free(msgT); g_free(msg); } proto->SessionStopping(); break; case mwSession_STOPPED: break; case mwSession_LOGIN_REDIR: proto->debugLog(_T("SessionStateChange() mwSession_LOGIN_REDIR info=[%s]"), _A2T((char*)info)); //options.server_name = str((char*)info); strcpy(proto->options.server_name, (char*)info); proto->LogOut(); proto->LogIn(proto->login_status, proto->m_hNetlibUser); break; case mwSession_LOGIN_CONT: break; case mwSession_LOGIN: break; case mwSession_LOGIN_ACK: break; case mwSession_UNKNOWN: break; } }
void __cdecl sttFakeAckMessageSuccessThread(void *param) { TFakeAckParams* tParam = (TFakeAckParams*)param; CSametimeProto* proto = tParam->proto; proto->debugLog(_T("sttFakeAckMessageSuccessThread() start")); Sleep(100); proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)tParam->lParam, 0); proto->debugLog(_T("sttFakeAckMessageSuccessThread() end")); mir_free(tParam); }
void __cdecl sttRecvAwayThread(void *param) { TFakeAckParams* tParam = (TFakeAckParams*)param; CSametimeProto* proto = tParam->proto; proto->debugLog(_T("sttRecvAwayThread() start")); Sleep(100); proto->UserRecvAwayMessage(tParam->hContact); proto->debugLog(_T("sttRecvAwayThread() end")); free(tParam); }
void __cdecl sttFakeAckMessageFailedThread(void *param) { TFakeAckParams* tParam = (TFakeAckParams*)param; CSametimeProto* proto = tParam->proto; proto->debugLog(_T("sttFakeAckMessageFailedThread() start")); Sleep(100); proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, NULL, tParam->lParam); ///TODO tParam->lParam: add error message proto->debugLog(_T("sttFakeAckMessageFailedThread() end")); mir_free(tParam); }
void __cdecl SessionClose(mwSession* session) { CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR"); proto->debugLog(_T("SessionClose() server_connection=[%d]"), proto->server_connection); Netlib_CloseHandle(proto->server_connection); proto->server_connection = 0; }
/** triggered when someone says something */ void mwServiceConf_on_text(mwConference* conf, mwLoginInfo* user, const char* what) { CSametimeProto* proto = getProtoFromMwConference(conf); proto->debugLog(_T("mwServiceConf_on_text() start")); TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf)); GCDEST gcd = { proto->m_szModuleName }; gcd.ptszID = tszConfId; gcd.iType = GC_EVENT_MESSAGE; GCEVENT gce = { sizeof(gce), &gcd }; gce.dwFlags = GCEF_ADDTOLOG; TCHAR* textT = mir_utf8decodeT(what); TCHAR* tszUserName = mir_utf8decodeT(user->user_name); TCHAR* tszUserId = mir_utf8decodeT(user->login_id); gce.ptszText = textT; gce.ptszNick = tszUserName; gce.ptszUID = tszUserId; gce.time = (DWORD)time(0); CallService(MS_GC_EVENT, 0, (LPARAM)(GCEVENT *) &gce); mir_free(textT); mir_free(tszUserName); mir_free(tszUserId); mir_free(tszConfId); }
/** received an ack for a sent chunk on an outbound file transfer. this indicates that a previous call to mwFileTransfer_send has reached the target and that the target has responded. */ void mwFileTransfer_handle_ack(mwFileTransfer* ft) { // see SendThread above - not all clients send us acks CSametimeProto* proto = getProtoFromMwFileTransfer(ft); //FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft); proto->debugLog(_T("mwFileTransfer_handle_ack()")); }
void __cdecl SessionAdmin(struct mwSession* session, const char* text) { CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR"); proto->debugLog(_T("SessionAdmin()")); TCHAR* tt = mir_utf8decodeT(text); MessageBox(0, tt, TranslateT("Sametime administrator message"), MB_OK); mir_free(tt); }
void __cdecl SendThread(LPVOID param) { mwFileTransfer* ft = (mwFileTransfer*)param; if (!ft) return; CSametimeProto* proto = getProtoFromMwFileTransfer(ft); FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft); proto->debugLog(_T("SendThread() start")); PROTOFILETRANSFERSTATUS pfts = {0}; pfts.cbSize = sizeof(pfts); pfts.flags = PFTS_UTF; pfts.hContact = ftcd->hContact; if (ftcd->sending == 1) pfts.flags |= PFTS_SENDING; pfts.pszFiles = NULL; pfts.totalFiles = ftcd->first->ft_count; pfts.totalBytes = ftcd->first->totalSize; while(SendFileChunk(proto, ft, ftcd) && !Miranda_Terminated()) { pfts.currentFileNumber = ftcd->ft_number; pfts.totalProgress = ftcd->sizeToHere + mwFileTransfer_getSent(ft); pfts.szWorkingDir = ftcd->save_path; pfts.szCurrentFile = (char*)mwFileTransfer_getFileName(ft); pfts.currentFileSize = mwFileTransfer_getFileSize(ft); pfts.currentFileProgress = mwFileTransfer_getSent(ft); pfts.currentFileTime = 0; //? proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ftcd->hFt, (LPARAM)&pfts); SleepEx(500,TRUE); } proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftcd->hFt, 0); mwFileTransfer_removeClientData(ft); if (ftcd->save_path) free(ftcd->save_path); if (ftcd->buffer) delete[] ftcd->buffer; delete ftcd; proto->debugLog(_T("SendThread() end")); return; }
int __cdecl SessionWrite(mwSession* session, const unsigned char* buf, gsize len) { CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR"); proto->debugLog(_T("SessionWrite() server_connection=[%d], len=[%d]"), proto->server_connection, len); if (!proto->server_connection) return 1; if (Netlib_Send(proto->server_connection, (const char*)buf, len, 0) == SOCKET_ERROR) return 1; return 0; }
/** receive a chunk of a file from an inbound file transfer. */ void mwFileTransfer_recv(mwFileTransfer* ft, struct mwOpaque* data) { CSametimeProto* proto = getProtoFromMwFileTransfer(ft); FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft); proto->debugLog(_T("mwFileTransfer_recv() start")); DWORD bytes_written; if (!WriteFile(ftcd->hFile, data->data, data->len, &bytes_written, 0)) { proto->debugLog(_T("mwFileTransfer_recv() !WriteFile")); mwFileTransfer_cancel(ft); proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ftcd->hFt, 0); proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_FAILED")); } else { mwFileTransfer_ack(ft); // acknowledge chunk PROTOFILETRANSFERSTATUS pfts = { 0 }; pfts.cbSize = sizeof(pfts); pfts.flags = PFTS_UTF; pfts.hContact = ftcd->hContact; if (ftcd->sending == 1) { pfts.flags |= PFTS_SENDING; } pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = mwFileTransfer_getFileSize(ft); pfts.totalProgress = mwFileTransfer_getSent(ft); pfts.szWorkingDir = ftcd->save_path; pfts.szCurrentFile = (char*)mwFileTransfer_getFileName(ft); pfts.currentFileSize = mwFileTransfer_getFileSize(ft); pfts.currentFileProgress = mwFileTransfer_getSent(ft); pfts.currentFileTime = 0; //? proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ftcd->hFt, (LPARAM)&pfts); proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_DATA")); if (mwFileTransfer_isDone(ft)) { proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftcd->hFt, 0); proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_SUCCESS")); } } }
/** a file transfer has been fully initiated */ void mwFileTransfer_opened(mwFileTransfer* ft) { CSametimeProto* proto = getProtoFromMwFileTransfer(ft); FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft); proto->debugLog(_T("Sametime mwFileTransfer_opened start")); if (ftcd->sending) { // create a thread to send chunks - since it seems not all clients send acks for each of our chunks! mir_forkthread(SendThread, ft); } }
/** an incoming file transfer has been offered */ void mwFileTransfer_offered(mwFileTransfer* ft) { CSametimeProto* proto = getProtoFromMwFileTransfer(ft); proto->debugLog(_T("mwFileTransfer_offered() start")); const mwIdBlock* idb = mwFileTransfer_getUser(ft); MCONTACT hContact = proto->FindContactByUserId(idb->user); proto->debugLog(_T("Sametime mwFileTransfer_offered hContact=[%x]"), hContact); if (!hContact) { mwSametimeList* user_list = mwSametimeList_new(); mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, Translate("None")); mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, (mwIdBlock*)idb); hContact = proto->AddContact(stuser, (proto->options.add_contacts ? false : true)); } proto->ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, (HANDLE)ft, 0); TCHAR* filenameT = mir_utf8decodeT(mwFileTransfer_getFileName(ft)); const char* message = mwFileTransfer_getMessage(ft); TCHAR descriptionT[512]; if (message) { TCHAR* messageT = mir_utf8decodeT(message); mir_sntprintf(descriptionT, _T("%s - %s"), filenameT, messageT); mir_free(messageT); } else _tcsncpy_s(descriptionT, filenameT, _TRUNCATE); PROTORECVFILET pre = {0}; pre.dwFlags = PRFF_TCHAR; pre.fileCount = 1; pre.timestamp = time(NULL); pre.descr.t = descriptionT; pre.files.t = &filenameT; pre.lParam = (LPARAM)ft; ProtoChainRecvFile(hContact, &pre); mir_free(filenameT); }
void __cdecl SessionAnnounce(struct mwSession* session, struct mwLoginInfo* from, gboolean may_reply, const char* text) { CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR"); proto->debugLog(_T("SessionAnnounce()")); TCHAR* stzFrom; TCHAR* stzText; TCHAR stzFromBuff[256]; stzFrom = mir_utf8decodeT(from->user_name); stzText = mir_utf8decodeT(text); mir_sntprintf(stzFromBuff, SIZEOF(stzFromBuff), TranslateT("Session announcement - from '%s'"), stzFrom); MessageBox(0, TranslateTS(stzText), stzFromBuff, MB_OK); mir_free(stzText); mir_free(stzFrom); }
/** triggered when a conference is closed. This is typically when we've left it */ void mwServiceConf_conf_closed(mwConference* conf, guint32 reason) { CSametimeProto* proto = getProtoFromMwConference(conf); proto->debugLog(_T("mwServiceConf_conf_closed() start")); TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf)); GCDEST gcd = { proto->m_szModuleName }; gcd.ptszID = tszConfId; gcd.iType = GC_EVENT_CONTROL; GCEVENT gce = { sizeof(gce), &gcd }; gce.dwFlags = GCEF_ADDTOLOG; CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce); CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce); mir_free(tszConfId); }
/** triggered when someone joins the conference */ void mwServiceConf_on_peer_joined(mwConference* conf, mwLoginInfo *user) { CSametimeProto* proto = getProtoFromMwConference(conf); proto->debugLog(_T("mwServiceConf_on_peer_joined() start")); MCONTACT hContact = proto->FindContactByUserId(user->user_id); if (!hContact) { mwIdBlock idb; idb.user = ((mwLoginInfo *)user)->user_id; idb.community = 0; mwSametimeList* user_list = mwSametimeList_new(); char* utfs = mir_utf8encodeT(TranslateT("None")); mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, utfs); mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, &idb); hContact = proto->AddContact(stuser, (proto->options.add_contacts ? false : true)); mwSametimeList_free(user_list); mir_free(utfs); } ptrT tszConfId(mir_utf8decodeT(mwConference_getName(conf))); ptrT tszUserName(mir_utf8decodeT(user->user_name)); ptrT tszUserId(mir_utf8decodeT(user->login_id)); // add user GCDEST gcd = { proto->m_szModuleName }; gcd.ptszID = tszConfId; gcd.iType = GC_EVENT_JOIN; GCEVENT gce = { sizeof(gce), &gcd }; gce.dwFlags = GCEF_ADDTOLOG; gce.ptszNick = tszUserName; gce.ptszUID = tszUserId; gce.ptszStatus = _T("Normal"); gce.time = (DWORD)time(0); CallServiceSync(MS_GC_EVENT, 0, (LPARAM) &gce); mir_free(tszUserName); mir_free(tszUserId); mir_free(tszConfId); }
/** triggered when someone leaves the conference */ void mwServiceConf_on_peer_parted(mwConference* conf, mwLoginInfo* user) { CSametimeProto* proto = getProtoFromMwConference(conf); proto->debugLog(_T("mwServiceConf_on_peer_parted() start")); ptrT tszConfId(mir_utf8decodeT(mwConference_getName(conf))); ptrT tszUserName(mir_utf8decodeT(user->user_name)); ptrT tszUserId(mir_utf8decodeT(user->login_id)); // remove user GCDEST gcd = { proto->m_szModuleName }; gcd.ptszID = tszConfId; gcd.iType = GC_EVENT_PART; GCEVENT gce = { sizeof(gce), &gcd }; gce.dwFlags = GCEF_ADDTOLOG; gce.ptszNick = tszUserName; gce.ptszUID = tszUserId; gce.ptszStatus = _T("Normal"); gce.time = (DWORD)time(0); CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); }
void __cdecl SessionSetUserStatus(struct mwSession* session) { CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR"); int new_status; struct mwUserStatus us; mwUserStatus_clone(&us, mwSession_getUserStatus(session)); proto->debugLog(_T("SessionSetUserStatus() us.status=[%d]"), us.status); switch (us.status) { case mwStatus_ACTIVE: new_status = ID_STATUS_ONLINE; break; case mwStatus_AWAY: new_status = ID_STATUS_AWAY; if (proto->idle_status) { // ignore setting to away by idle module, after we've set ourselves idle // most standard clients represent idle and away the same way anyway, // but this allows miranda users to make use of the idle timestamp // but show our status in clist as away proto->BroadcastNewStatus(new_status); mwUserStatus_clear(&us); return; } break; case mwStatus_BUSY: new_status = ID_STATUS_DND; break; case mwStatus_IDLE: new_status = ID_STATUS_AWAY; if (!proto->first_online && !proto->options.idle_as_away) { // show our status in clist as away if idle when going online or treating idle as away mwUserStatus_clear(&us); return; } break; case mwStatus_IN_MEETING: // new 'in meeting' status new_status = ID_STATUS_OCCUPIED; break; default: TCHAR buff[512]; mir_sntprintf(buff, SIZEOF(buff), TranslateT("Unknown user status: %d"), us.status); proto->showPopup(buff, SAMETIME_POPUP_ERROR); proto->debugLog(buff); mwUserStatus_clear(&us); // just go online...to prevent us getting stuck 'connecting' new_status = ID_STATUS_ONLINE; break; } proto->m_iDesiredStatus = new_status; if (proto->first_online) { proto->first_online = false; //proto->showPopup(TranslateT("Setting login status"), SAMETIME_POPUP_INFO); proto->debugLog(_T("Setting login status")); proto->SetSessionStatus(proto->login_status); } else proto->BroadcastNewStatus(new_status); mwUserStatus_clear(&us); }
void __cdecl SessionSetPrivacyInfo(struct mwSession* session) { CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR"); proto->debugLog(_T("SessionSetPrivacyInfo()")); }
void __cdecl SessionClear(mwSession* session) { CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR"); proto->debugLog(_T("SessionClear()")); }
/** typing notification */ void mwServiceConf_on_typing(mwConference* conf, mwLoginInfo* who, gboolean typing) { CSametimeProto* proto = getProtoFromMwConference(conf); proto->debugLog(_T("mwServiceConf_on_typing() start")); ///TODO unimplemented }
void LogFromGLib(const gchar* log_domain, GLogLevelFlags log_level, const gchar* message, gpointer user_data) { CSametimeProto* proto = (CSametimeProto*)user_data; proto->debugLog(_A2T(message)); }
/** triggered when we enter the conference. Provides the initial conference membership list as a GList of mwLoginInfo structures @param conf the conference just joined @param members mwLoginInfo list of existing conference members */ void mwServiceConf_conf_opened(mwConference* conf, GList* members) { CSametimeProto* proto = getProtoFromMwConference(conf); proto->debugLog(_T("mwServiceConf_conf_opened() start")); TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf)); TCHAR* tszConfTitle = mir_utf8decodeT(mwConference_getTitle(conf)); // create new chat session GCSESSION gcs = { sizeof(gcs) }; gcs.dwFlags = 0; gcs.iType = GCW_CHATROOM; gcs.pszModule = proto->m_szModuleName; gcs.ptszID = tszConfId; gcs.ptszName = tszConfTitle; gcs.dwItemData = 0; CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcs); mir_free(tszConfTitle); //add a group GCDEST gcd = { proto->m_szModuleName, 0 }; gcd.iType = GC_EVENT_ADDGROUP; gcd.ptszID = tszConfId; GCEVENT gce = { sizeof(gce), &gcd }; gce.dwFlags = GCEF_ADDTOLOG; gce.ptszStatus = TranslateT("Normal"); CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); // add users gcd.iType = GC_EVENT_JOIN; GList *user = members; for (;user; user=user->next) { proto->debugLog(_T("mwServiceConf_conf_opened() add user")); TCHAR* tszUserName = mir_utf8decodeT(((mwLoginInfo*)user->data)->user_name); TCHAR* tszUserId = mir_utf8decodeT(((mwLoginInfo*)user->data)->login_id); gce.ptszNick = tszUserName; gce.ptszUID = tszUserId; gce.bIsMe = (strcmp(((mwLoginInfo*)user->data)->login_id, proto->my_login_info->login_id) == 0); CallServiceSync(MS_GC_EVENT, 0, (LPARAM) &gce); mir_free(tszUserName); mir_free(tszUserId); } // finalize setup (show window) gcd.iType = GC_EVENT_CONTROL; CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce); gcd.iType = GC_EVENT_CONTROL; CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce); if (conf == proto->my_conference) proto->ClearInviteQueue(); mir_free(tszConfId); }
INT_PTR CALLBACK SessionAnnounceDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { SessionAnnounceDialogProc_arg* arg = (SessionAnnounceDialogProc_arg*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); CSametimeProto *proto; switch (uMsg) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); { SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); arg = (SessionAnnounceDialogProc_arg*)lParam; proto = arg->proto; proto->debugLog(_T("SessionAnnounceDialogProc WM_INITDIALOG")); SendDlgItemMessage(hwndDlg, IDC_LST_ANTO, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); { LVCOLUMN lvc; // Initialize the LVCOLUMN structure. // The mask specifies that the format, width, text, and // subitem members of the structure are valid. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.fmt = LVCFMT_LEFT; lvc.iSubItem = 0; lvc.pszText = TranslateT("Recipients"); lvc.cx = 300; // width of column in pixels ListView_InsertColumn(GetDlgItem(hwndDlg, IDC_LST_ANTO), 0, &lvc); } //enumerate plugins, fill in list { ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_LST_ANTO)); LVITEM lvI; // Some code to create the list-view control. // Initialize LVITEM members that are common to all items. lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_NORECOMPUTE;// | LVIF_IMAGE; lvI.iItem = 0; lvI.iSubItem = 0; for (MCONTACT hContact = db_find_first(proto->m_szModuleName); hContact; hContact = db_find_next(hContact, proto->m_szModuleName)) { if (db_get_b(hContact, proto->m_szModuleName, "ChatRoom", 0) == 0 && db_get_w(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) { lvI.lParam = (LPARAM)hContact; lvI.pszText = pcli->pfnGetContactDisplayName(hContact, 0); ListView_InsertItem(GetDlgItem(hwndDlg, IDC_LST_ANTO), &lvI); lvI.iItem++; } } } } return 0; case WM_CLOSE: proto = arg->proto; proto->debugLog(_T("SessionAnnounceDialogProc WM_CLOSE")); mir_free(arg); DestroyWindow(hwndDlg); break; case WM_COMMAND: proto = arg->proto; if (HIWORD(wParam) == BN_CLICKED) { int size; switch (LOWORD(wParam)) { case IDC_BUT_SELALL: size = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_LST_ANTO)); for (int i = 0; i < size; i++) ListView_SetCheckState(GetDlgItem(hwndDlg, IDC_LST_ANTO), i, true); return 0; case IDC_BUT_SELINV: size = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_LST_ANTO)); for (int i = 0; i < size; i++) ListView_SetCheckState(GetDlgItem(hwndDlg, IDC_LST_ANTO), i, !ListView_GetCheckState(GetDlgItem(hwndDlg, IDC_LST_ANTO), i)); return 0; case IDOK: proto->debugLog(_T("SessionAnnounceDialogProc IDOK BN_CLICKED")); { // build SendAnnouncementFunc_arg SendAnnouncementFunc_arg* safArg = (SendAnnouncementFunc_arg*)mir_calloc(sizeof(SendAnnouncementFunc_arg)); DBVARIANT dbv; LVITEM lvI = { 0 }; char id[1024]; mir_strcpy(id, "@U"); // documentation says prepend '@U' to usernames and '@G' to notes group names - but char *p = id + 2; // it's wrong - it works for a list of user id's with no prefix - so we'll do both // build recipient list safArg->recipients = 0; int size = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_LST_ANTO)); int send_count = 0; for (int i = 0; i < size; i++) { if (ListView_GetCheckState(GetDlgItem(hwndDlg, IDC_LST_ANTO), i)) { lvI.iItem = i; lvI.iSubItem = 0; lvI.mask = LVIF_PARAM; ListView_GetItem(GetDlgItem(hwndDlg, IDC_LST_ANTO), &lvI); if (!db_get_utf((MCONTACT)lvI.lParam, proto->m_szModuleName, "stid", &dbv)) { safArg->recipients = g_list_prepend(safArg->recipients, _strdup(dbv.pszVal)); mir_strcpy(p, dbv.pszVal); safArg->recipients = g_list_prepend(safArg->recipients, _strdup(id)); send_count++; db_free(&dbv); } } } if (send_count > 0) { GetDlgItemText(hwndDlg, IDC_ED_ANMSG, safArg->msg, MAX_MESSAGE_SIZE); safArg->proto = proto; SendAnnouncementFunc sendAnnouncementFunc = arg->sendAnnouncementFunc; sendAnnouncementFunc(safArg); } // clean up recipient list if (safArg->recipients) { for (GList *rit = safArg->recipients; rit; rit = rit->next) { free(rit->data); } g_list_free(safArg->recipients); } mir_free(safArg); DestroyWindow(hwndDlg); } return 0; case IDCANCEL: DestroyWindow(hwndDlg); return 0; } } break; } return 0; }
void __cdecl SessionThread(LPVOID param) { CSametimeProto* proto = (CSametimeProto*)param; HANDLE hNetlibUser = proto->m_hNetlibUser; proto->debugLog(_T("SessionThread() start")); continue_connect = true; //setup NETLIBOPENCONNECTION conn_data = { 0 }; conn_data.cbSize = sizeof(NETLIBOPENCONNECTION); conn_data.flags = NLOCF_V2; conn_data.szHost = proto->options.server_name; conn_data.wPort = proto->options.port; conn_data.timeout = 20; conn_data.waitcallback = waitcallback; proto->BroadcastNewStatus(ID_STATUS_CONNECTING); proto->server_connection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlibUser, (LPARAM)&conn_data); if (!proto->server_connection) { proto->BroadcastNewStatus(ID_STATUS_OFFLINE); if (continue_connect) { // real timeout - not user cancelled proto->showPopup(TranslateT("No server connection!"), SAMETIME_POPUP_ERROR); } proto->debugLog(_T("SessionThread() end, no server_connection, continue_connect=[%d]"), continue_connect); return; } mwSessionHandler handler = { 0 }; handler.clear = SessionClear; handler.io_write = SessionWrite; handler.io_close = SessionClose; handler.on_stateChange = SessionStateChange; handler.on_admin = SessionAdmin; handler.on_announce = SessionAnnounce; handler.on_setPrivacyInfo = SessionSetPrivacyInfo; handler.on_setUserStatus = SessionSetUserStatus; EnterCriticalSection(&proto->session_cs); proto->session = mwSession_new(&handler); proto->InitMeanwhileServices(); mwSession_start(proto->session); LeaveCriticalSection(&proto->session_cs); mir_forkthread(KeepAliveThread, (void*)proto); unsigned char* recv_buffer = (unsigned char*)mir_alloc(1024 * 32); int bytes; //while(session && server_connection && mwSession_getState(session) != mwSession_STOPPED) { while (proto->server_connection) {// && session) {// && !mwSession_isStopped(session)) { // break on error bytes = Netlib_Recv(proto->server_connection, (char *)recv_buffer, 1024 * 32, 0); proto->debugLog(_T("SessionThread() Netlib_Recv'ed bytes=[%d]"), bytes); if (bytes == 0) { break; } else if (bytes == SOCKET_ERROR) { // this is normal - e.g. socket closed due to log off, during blocking read above break; } else { EnterCriticalSection(&proto->session_cs); mwSession_recv(proto->session, recv_buffer, bytes); LeaveCriticalSection(&proto->session_cs); } } mir_free(recv_buffer); EnterCriticalSection(&proto->session_cs); proto->DeinitMeanwhileServices(); mwSession* old_session = proto->session; proto->session = 0; // kills keepalive thread, if awake mwSession_free(old_session); LeaveCriticalSection(&proto->session_cs); proto->BroadcastNewStatus(ID_STATUS_OFFLINE); proto->SetAllOffline(); proto->first_online = true; proto->debugLog(_T("SessionThread() end")); return; }
/** a file transfer has been closed. Check the status of the file transfer to determine if the transfer was complete or if it had been interrupted */ void mwFileTransfer_closed(mwFileTransfer* ft, guint32 code) { CSametimeProto* proto = getProtoFromMwFileTransfer(ft); FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft); proto->debugLog(_T("mwFileTransfer_closed() start")); if (ftcd) { if (ftcd->hFile != INVALID_HANDLE_VALUE) CloseHandle(ftcd->hFile); if (code != mwFileTransfer_SUCCESS || !mwFileTransfer_isDone(ft)) { if (!ftcd->sending) { char fn[MAX_PATH]; if (ftcd->save_path) mir_strcpy(fn, ftcd->save_path); else fn[0] = 0; mir_strcat(fn, mwFileTransfer_getFileName(ft)); DeleteFileA(fn); } if (code == mwFileTransfer_REJECTED) proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ftcd->hFt, 0); else proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ftcd->hFt, 0); if (ftcd->sending) { FileTransferClientData* ftcd_next = ftcd->next; while(ftcd_next) { mwFileTransfer_free((mwFileTransfer*)ftcd_next->ft); FileTransferClientData *ftcd_temp = ftcd_next->next; if (ftcd_next->hFile != INVALID_HANDLE_VALUE) CloseHandle(ftcd_next->hFile); if (ftcd_next->save_path) free(ftcd_next->save_path); if (ftcd_next->buffer) delete[] ftcd_next->buffer; delete ftcd_next; ftcd_next = ftcd_temp; } } else { mwFileTransfer_removeClientData(ft); if (ftcd->save_path) free(ftcd->save_path); if (ftcd->buffer) delete[] ftcd->buffer; delete ftcd; mwFileTransfer_free(ft); } } else { if (ftcd->sending) { // check if we have more files to send... if (ftcd->next) { proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ftcd->hFt, 0); mwFileTransfer_offer(ftcd->next->ft); } } else { proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftcd->hFt, 0); mwFileTransfer_removeClientData(ft); if (ftcd->save_path) free(ftcd->save_path); if (ftcd->buffer) delete[] ftcd->buffer; delete ftcd; mwFileTransfer_free(ft); } } } }