123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #include "precompile.h"
- #include "sp_sps.h"
- #include "sp_def.h"
- #include "sp_logwithlinkforc.h"
- #include "memutil.h"
- #include <winpr/winsock.h>
- #define SILVERLIGHT_POLICY_PORT 943
- #define MAX_TIMEOUT 30000
- static const char *req_policy = "<policy-file-request/>";
- static const int req_policy_len = 22;
- static const char *res_policy =
- "<?xml version=\"1.0\" encoding =\"utf-8\"?>\r\n"
- "<access-policy>\r\n"
- " <cross-domain-access>\r\n"
- " <policy>\r\n"
- " <allow-from>\r\n"
- " <domain uri=\"*\" />\r\n"
- " </allow-from>\r\n"
- " <grant-to>\r\n"
- " <socket-resource port=\"4502-4506\" protocol=\"tcp\" />\r\n"
- " </grant-to>\r\n"
- " </policy>\r\n"
- " </cross-domain-access>\r\n"
- "</access-policy>\r\n";
- static const int res_policy_len = 323;
- struct sp_sps_t
- {
- WSAEVENT evt_ready;
- int result;
- WSAEVENT evt_stop;
- HANDLE worker_thread;
- };
- static void __on_accept(SOCKET policy_fd)
- {
- struct sockaddr_in from_addr;
- int from_len = sizeof(from_addr);
- SOCKET conn_fd = accept(policy_fd, (struct sockaddr*)&from_addr, &from_len);
- u_long iMode = 0;
- int recved = 0;
- char req_buf[512];
- int buf_len = sizeof(req_buf);
- int sended = 0;
- int need_send = res_policy_len;
- BOOL opt;
- if (conn_fd == INVALID_SOCKET) {
- DbgWithLinkForC(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM, "accept new connection fd failed!");
- return;
- }
- DbgWithLinkForC(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM, "accept from %s:%d", inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));
- WSAEventSelect(conn_fd, NULL, 0);
- _ioctlsocket(conn_fd, FIONBIO, &iMode);
- opt = TRUE;
- setsockopt(conn_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
- opt = TRUE;
- setsockopt(conn_fd, SOL_SOCKET, SO_DONTLINGER, (char*)&opt, sizeof(opt));
- while (recved < req_policy_len) {
- int t = recv(conn_fd, req_buf+recved, req_policy_len-recved, 0);
- if (t <= 0) {
- DbgWithLinkForC(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM, "recv conn_fd failed! error:%d", WSAGetLastError());
- goto on_error;
- } else {
- recved += t;
- }
- }
- if (_strnicmp(req_policy, req_buf, req_policy_len) != 0) {
- DbgWithLinkForC(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM, "warning: req_buf not equal to <policy-file-request/>!!!");
- goto on_error;
- }
- while (sended < need_send) {
- int t = send(conn_fd, res_policy+sended, res_policy_len-sended, 0);
- if (t <= 0) {
- DbgWithLinkForC(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM, "send res policy failed!");
- goto on_error;
- } else {
- sended += t;
- }
- }
- shutdown(conn_fd, SD_BOTH);
- on_error:
- closesocket(conn_fd);
- }
- static unsigned int __stdcall __sps_worker_proc(void *arg)
- {
- sp_sps_t *sps = (sp_sps_t*)arg;
- WSAEVENT evt[2] = {sps->evt_stop};
- SOCKET fd = INVALID_SOCKET;
- struct sockaddr_in addr = {0};
- fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (fd == INVALID_SOCKET) {
- sps->result = -1;
- goto on_start_error;
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(SILVERLIGHT_POLICY_PORT);
- addr.sin_addr.s_addr = htonl(INADDR_ANY); // only for debug
- //addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) != 0 || listen(fd, 5) != 0) {
- sps->result = -1;
- goto on_start_error;
- }
- evt[1] = WSACreateEvent();
- WSAEventSelect(fd, evt[1], FD_ACCEPT | FD_CLOSE);
- sps->result = 0;
- WSASetEvent(sps->evt_ready);
- for(;;) {
- DWORD dwRet = WSAWaitForMultipleEvents(ARRAYSIZE(evt), &evt[0], FALSE, MAX_TIMEOUT, FALSE);
- if (dwRet == WSA_WAIT_EVENT_0) {
- break; // stop
- } else if (dwRet == WSA_WAIT_EVENT_0+1) {
- WSANETWORKEVENTS netevents;
- if (WSAEnumNetworkEvents(fd, evt[1], &netevents) != SOCKET_ERROR) {
- if (netevents.lNetworkEvents & FD_ACCEPT) {
- if (netevents.iErrorCode[FD_ACCEPT_BIT] == 0) {
- __on_accept(fd);
- }
- }
- if (netevents.lNetworkEvents & FD_CLOSE) {
- DbgWithLinkForC(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM, "accept closed! err %d %s %d", WSAGetLastError(), _GetFileName(__FILE__), __LINE__);
- break;
- }
- } else {
- DbgWithLinkForC(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM, "WSAGetLastError %d %s %d", WSAGetLastError(), _GetFileName(__FILE__), __LINE__);
- }
- } else if (dwRet == WSA_WAIT_TIMEOUT) {
- continue;
- } else {
- break;
- }
- }
- on_start_error:
- if (evt[1]) {
- WSAEventSelect(fd, evt[1], 0);
- WSACloseEvent(evt[1]);
- evt[1] = NULL;
- }
- if (fd != INVALID_SOCKET) {
- closesocket(fd);
- }
- WSASetEvent(sps->evt_ready);
- return sps->result;
- }
- int sp_sps_create(sp_sps_t **p_sps)
- {
- sp_sps_t *sps = MALLOC_T(sp_sps_t);
- sps->evt_ready = WSACreateEvent();
- sps->evt_stop = WSACreateEvent();
- sps->worker_thread = NULL;
- *p_sps = sps;
- return 0;
- }
- int sp_sps_start(sp_sps_t *sps)
- {
- WSAResetEvent(sps->evt_ready);
- WSAResetEvent(sps->evt_stop);
- sps->result = 0;
- sps->worker_thread = (HANDLE)_beginthreadex(NULL, 0, &__sps_worker_proc, sps, 0, NULL);
- if (sps->worker_thread) {
- WSAEVENT evt[1] = {sps->evt_ready};
- WSAWaitForMultipleEvents(1, &evt[0], FALSE, WSA_INFINITE, FALSE);
- if (sps->result != 0) {
- WaitForSingleObject(sps->worker_thread, INFINITE);
- CloseHandle(sps->worker_thread);
- sps->worker_thread = NULL;
- }
- return sps->result;
- } else {
- return Error_Resource;
- }
- }
- void sp_sps_destroy(sp_sps_t *sps)
- {
- WSACloseEvent(sps->evt_ready);
- WSACloseEvent(sps->evt_stop);
- free(sps);
- }
- void sp_sps_stop(sp_sps_t *sps)
- {
- WSASetEvent(sps->evt_stop);
- WaitForSingleObject(sps->worker_thread, INFINITE);
- CloseHandle(sps->worker_thread);
- sps->worker_thread = NULL;
- }
|