diff options
Diffstat (limited to 'protocols/SkypeClassic/src/skypeapi.cpp')
-rw-r--r-- | protocols/SkypeClassic/src/skypeapi.cpp | 168 |
1 files changed, 140 insertions, 28 deletions
diff --git a/protocols/SkypeClassic/src/skypeapi.cpp b/protocols/SkypeClassic/src/skypeapi.cpp index ebc74afeda..0f67db8ee4 100644 --- a/protocols/SkypeClassic/src/skypeapi.cpp +++ b/protocols/SkypeClassic/src/skypeapi.cpp @@ -7,7 +7,7 @@ #include "utf8.h"
#include "debug.h"
#include "contacts.h"
-#include "skypeproxy.h"
+#include "skypeproxy/skypeproxy.h"
#include "pthread.h"
#include "gchat.h"
#include "alogon.h"
@@ -50,13 +50,14 @@ status_map status_codes[] = { //status_map
-static CRITICAL_SECTION ConnectMutex;
+static CRITICAL_SECTION ConnectMutex, SendMutex;
static BOOL rcvThreadRunning=FALSE, isConnecting = FALSE;
static SOCKET ClientSocket=INVALID_SOCKET;
static HANDLE SkypeMsgToSend=NULL;
static char *m_szSendBuf = NULL;
static DWORD m_iBufSize = 0;
+static HANDLE m_FileSlots[255]={INVALID_HANDLE_VALUE};
static int _ConnectToSkypeAPI(char *path, BOOL bStart);
@@ -78,9 +79,27 @@ INT_PTR SkypeReceivedAPIMessage(WPARAM wParam, LPARAM lParam) { * Skype via Socket --> Skype2Socket connection
*/
+static int Recv(SOCKET s, char *buf, int len) {
+ int ret,cnt=0;
+
+ do
+ {
+ if ((ret=recv(s,buf,len,0))==SOCKET_ERROR) {
+ LOG(("Recv() Socket error"));
+ return 0;
+ }
+ if (ret==0) break;
+ cnt+=ret;
+ buf+=ret;
+ len-=ret;
+ } while (len);
+ return len?0:cnt;
+}
+
void rcvThread(char *dummy) {
+ unsigned char cmd=0, nSlot;
unsigned int length;
- char *buf;
+ char *buf=NULL;
COPYDATASTRUCT CopyData;
int rcv;
@@ -92,31 +111,102 @@ void rcvThread(char *dummy) { return;
}
LOG(("rcvThread Receiving from socket.."));
- if ((rcv=recv(ClientSocket, (char *)&length, sizeof(length), 0))==SOCKET_ERROR || rcv==0) {
+ if (!(rcv=Recv(ClientSocket, (char *)&length, sizeof(length))) || length>0x10000000) {
rcvThreadRunning=FALSE;
if (rcv==SOCKET_ERROR) {LOG(("rcvThread Socket error"));}
else {LOG(("rcvThread lost connection, graceful shutdown"));}
return;
}
+ EnterCriticalSection(&SendMutex);
+ if (length == 0) {
+ unsigned short lenfn;
+ char szFileName[MAX_PATH], *pszUTFFile=NULL;
+
+ // Command mode
+ if ((rcv = Recv(ClientSocket, (char*)&cmd, sizeof(cmd)))) {
+ switch (cmd)
+ {
+ case OPEN_SLOT:
+ LOG(("rcvThread OPEN_SLOT"));
+ if (!(rcv = Recv(ClientSocket, (char*)&lenfn, sizeof(lenfn))) ||
+ !(rcv = Recv(ClientSocket, szFileName, lenfn))) {
+ LOG(("OPEN_SLOT failed: rcv=%d", rcv));
+ rcv=0;
+ break;
+ }
+
+ utf8_decode(szFileName, &pszUTFFile);
+ for (nSlot=0; nSlot<sizeof(m_FileSlots)/sizeof(m_FileSlots[0]); nSlot++)
+ if (m_FileSlots[nSlot]==INVALID_HANDLE_VALUE) break;
+ if (nSlot>=sizeof(m_FileSlots)/sizeof(m_FileSlots[0])) cmd=0;
+ else {
+ if ((m_FileSlots[nSlot] = CreateFileA(pszUTFFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
+ !=INVALID_HANDLE_VALUE) nSlot++; else nSlot=0;
+ }
+ free(pszUTFFile);
+ LOG(("rcvThread OPEN_SLOT(%s) -> %d", szFileName, nSlot));
+ if ((rcv=send(ClientSocket, (char *)&nSlot, sizeof(nSlot), 0)) == SOCKET_ERROR || rcv==0) rcv=0;
+ else {
+ LeaveCriticalSection(&SendMutex);
+ continue;
+ }
+ break;
+ case DATA_SLOT:
+ LOG(("rcvThread DATA_SLOT"));
+ if (!(rcv=Recv(ClientSocket, (char*)&nSlot, sizeof(nSlot))) || !nSlot ||
+ !(rcv=Recv(ClientSocket, (char *)&length, sizeof(length))) || length>0x10000000) {
+ LOG(("DATA_SLOT failed: rcv=%d", rcv));
+ rcv=0;
+ }
+ break;
+ case CLOSE_SLOT:
+ LOG(("rcvThread CLOSE_SLOT"));
+ if (!(rcv = Recv(ClientSocket, (char*)&nSlot, sizeof(nSlot)))) {
+ LOG(("CLOSE_SLOT failed: rcv=%d"));
+ rcv=0;
+ break;
+ }
+ LOG(("rcvThread CLOSE_SLOT(%d)", nSlot));
+ CloseHandle(m_FileSlots[nSlot-1]);
+ m_FileSlots[nSlot-1]=INVALID_HANDLE_VALUE;
+ if (rcv) {
+ LeaveCriticalSection(&SendMutex);
+ continue;
+ }
+ break;
+ }
+ }
+ }
LOG(("rcvThread Received length, recieving message.."));
buf=(char *)calloc(1, length+1);
- if ((rcv = recv(ClientSocket, buf, length, 0))==SOCKET_ERROR || rcv==0) {
+ if (rcv==0 || !(buf=(char *)calloc(1, length+1)) ||
+ !(rcv = Recv(ClientSocket, buf, length))) {
rcvThreadRunning=FALSE;
- if (rcv==SOCKET_ERROR) {LOG(("rcvThread Socket error"));}
- else {LOG(("rcvThread lost connection, graceful shutdown"));}
+ LOG(("rcvThread lost connection, graceful shutdown"));
free(buf);
+ LeaveCriticalSection(&SendMutex);
return;
}
- LOG(("Received message: %s", buf));
+ if (cmd==DATA_SLOT) {
+ DWORD dwWritten;
- CopyData.dwData=0;
- CopyData.lpData=buf;
- CopyData.cbData=(DWORD)strlen(buf)+1;
- if (!SendMessage(g_hWnd, WM_COPYDATALOCAL, (WPARAM)hSkypeWnd, (LPARAM)&CopyData))
- {
- LOG(("SendMessage failed: %08X", GetLastError()));
+ LOG(("Received data packet with %u bytes", length));
+ if ((cmd = (char)WriteFile(m_FileSlots[nSlot-1], buf, length, &dwWritten, NULL)) && dwWritten!=length)
+ cmd=0;
+ //send(ClientSocket, (char *)&cmd, sizeof(cmd), 0);
+ } else {
+ LOG(("Received message: %s", buf));
+
+ CopyData.dwData=0;
+ CopyData.lpData=buf;
+ CopyData.cbData=(DWORD)strlen(buf)+1;
+ if (!SendMessage(g_hWnd, WM_COPYDATALOCAL, (WPARAM)hSkypeWnd, (LPARAM)&CopyData))
+ {
+ LOG(("SendMessage failed: %08X", GetLastError()));
+ }
}
free(buf);
+ LeaveCriticalSection(&SendMutex);
}
}
@@ -133,12 +223,15 @@ void sendThread(char *dummy) { length=(unsigned int)strlen(szMsg);
if (UseSockets) {
+ EnterCriticalSection(&SendMutex);
if (send(ClientSocket, (char *)&length, sizeof(length), 0) != SOCKET_ERROR &&
send(ClientSocket, szMsg, length, 0) != SOCKET_ERROR) {
free (szMsg);
+ LeaveCriticalSection(&SendMutex);
continue;
}
SendResult = 0;
+ LeaveCriticalSection(&SendMutex);
} else {
CopyData.dwData=0;
CopyData.lpData=szMsg;
@@ -196,7 +289,8 @@ int SkypeMsgInit(void) { MsgQ_Init(&SkypeMsgs);
MsgQ_Init(&SkypeSendQueue);
- InitializeCriticalSection(&ConnectMutex);
+ InitializeCriticalSection(&ConnectMutex);
+ InitializeCriticalSection(&SendMutex);
if (SkypeMsgToSend=CreateSemaphore(NULL, 0, MAX_MSGS, NULL)) {
if (m_szSendBuf = (char*)malloc(m_iBufSize=512)) {
if (_beginthread(( pThreadFunc )sendThread, 0, NULL)!=-1)
@@ -241,6 +335,7 @@ void SkypeMsgCleanup(void) { MsgQ_Exit(&SkypeMsgs);
LeaveCriticalSection(&ConnectMutex);
DeleteCriticalSection(&ConnectMutex);
+ DeleteCriticalSection(&SendMutex);
CloseHandle(SkypeMsgToSend);
SkypeMsgToSend=NULL;
MsgQ_Exit(&SkypeSendQueue);
@@ -278,7 +373,7 @@ static int __sendMsg(char *szMsg) { return 0;
}
- if (UseSockets && ClientSocket==INVALID_SOCKET) return -1;
+ if (UseSockets && (ClientSocket==INVALID_SOCKET)) return -1;
if (!MsgQ_Add(&SkypeSendQueue, szMsg) || !ReleaseSemaphore(SkypeMsgToSend, 1, NULL))
return -1;
return 0;
@@ -380,9 +475,12 @@ char *SkypeRcvTime(char *what, time_t st, DWORD maxwait) { msg=MsgQ_RemoveMsg(&SkypeMsgs, ptr);
LOG(("<SkypeRcv: %s", msg));
if (bIsChatMsg) {
- msg=(char*)realloc(msg, strlen(msg)+5);
- memmove (msg+4, msg, strlen(msg)+1);
- memcpy (msg, "CHAT", 4);
+ char *pmsg = (char*)realloc(msg, strlen(msg)+5);
+ if (pmsg) {
+ msg = pmsg;
+ memmove (msg+4, msg, strlen(msg)+1);
+ memcpy (msg, "CHAT", 4);
+ }
// This may be a sign that protocol negotiation failed, so we can try to send
// our supported protocol version again, just in case... (Skype API bug?)
@@ -559,6 +657,14 @@ WCHAR *SkypeGetErrW(char *szWhat, TCHAR *szWho, char *szProperty) { }
#endif
+char *SkypeGetErrID(char *szWhat, char *szWho, char *szProperty) {
+ char *ret = SkypeGetID(szWhat, szWho, szProperty);
+ if (ret && !strncmp(ret, "ERROR", 5)) {
+ free (ret);
+ return NULL;
+ }
+ return ret;
+}
/* SkypeGetProfile
*
@@ -1130,7 +1236,7 @@ INT_PTR SkypeSetAvatar(WPARAM wParam, LPARAM lParam) { }
-/* SkypeSendFile
+/* SkypeSendGuiFile
*
* Purpose: Opens the Skype-dialog to send a file
* Params : wParam - Handle to the User
@@ -1138,7 +1244,7 @@ INT_PTR SkypeSetAvatar(WPARAM wParam, LPARAM lParam) { * Returns: 0 - Success
* -1 - Failure
*/
-INT_PTR SkypeSendFile(WPARAM wParam, LPARAM lParam) {
+INT_PTR SkypeSendGuiFile(WPARAM wParam, LPARAM) {
DBVARIANT dbv;
int retval;
@@ -1421,10 +1527,9 @@ static int _ConnectToSkypeAPI(char *path, int iStart) { if ( connect( ClientSocket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR) return -1;
+ char reply=0;
if (db_get_b(NULL, SKYPE_PROTONAME, "RequiresPassword", 0) && !db_get_s(NULL, SKYPE_PROTONAME, "Password", &dbv))
{
- char reply=0;
-
if ((reply=SendSkypeproxyCommand(AUTHENTICATE))==-1) {
db_free(&dbv);
return -1;
@@ -1434,8 +1539,7 @@ static int _ConnectToSkypeAPI(char *path, int iStart) { db_set_b(NULL, SKYPE_PROTONAME, "RequiresPassword", 0);
} else {
unsigned int length=(unsigned int)strlen(dbv.pszVal);
- BOOL res;
- res = send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR
+ BOOL res = send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR
|| send(ClientSocket, dbv.pszVal, length, 0)==SOCKET_ERROR
|| recv(ClientSocket, (char *)&reply, sizeof(reply), 0)==SOCKET_ERROR;
if (res)
@@ -1451,18 +1555,26 @@ static int _ConnectToSkypeAPI(char *path, int iStart) { }
}
db_free(&dbv);
+ if ((reply=SendSkypeproxyCommand(CAPABILITIES))==-1) return -1;
}
else
{
- char reply=0;
-
if ((reply=SendSkypeproxyCommand(CAPABILITIES))==-1) return -1;
if (reply&USE_AUTHENTICATION) {
OUTPUT(_T("The server you specified requires authentication, but you have not supplied a password for it. Check the Skype plugin settings and try again."));
return -1;
}
}
-
+ if (reply&USE_DATASLOTS) {
+ unsigned int length=0;
+ char command=MY_CAPABILITIES, caps=USE_DATASLOTS;
+
+ // The server can send us datafiles, tell him that we support this
+ if ( send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR
+ || send(ClientSocket, (char *)&command, sizeof(command), 0)==SOCKET_ERROR
+ || send(ClientSocket, (char *)&caps, sizeof(caps), 0)==SOCKET_ERROR)
+ return -1;
+ }
if (!rcvThreadRunning)
if(_beginthread(( pThreadFunc )rcvThread, 0, NULL)==-1) return -1;
|