//ハンドルの解放 //解放後handleはNULLに void UPNP_SERVER_CloseHandle( UPNP_SERVER_HANDLE* handle //[IN]UPNP_SERVER_CreateHandleの戻り値 ) { UPNP_SSDP_HANDLE_ITEM* item = NULL; if( handle == NULL ){ return; } item = (UPNP_SSDP_HANDLE_ITEM*)*handle; if(item != NULL ){ if( item->notifySendThread != NULL ){ UPNP_SERVER_StopNotifySend(item); } if( item->ssdpSrvThread != NULL ){ _UPNP_SERVER_StopSSDP(item); } MP_LOCK_CloseHandle(&item->lockHandle); SORT_LIST_CloseHandle(&item->ssdpSockList); SORT_LIST_CloseHandle(&item->recvThreadList); SORT_LIST_CloseHandle(&item->notifyDeviceList); #ifdef _WIN32 WSACleanup(); #endif free(item); } *handle = NULL; }
void UPNP_MSEARCH_HANDLE_ITEM_Close(UPNP_MSEARCH_HANDLE_ITEM* item) { if( item == NULL ){ return; } if( item->msearchThread != NULL ){ item->msearchStopFlag = 1; MP_THREAD_WaitEndThread(&(item->msearchThread)); } MP_LOCK_CloseHandle(&item->lockHandle); SORT_LIST_CloseHandle(&item->resultList); free(item); }
int UPNP_UTIL_CreateUUID(char* uuid, int uuidSize, unsigned short deviceType, unsigned short uniqueID, unsigned short value) { SORT_LIST_HANDLE nicList = NULL; MP_NIC_INFO* nicInfo = NULL; unsigned int key = 0x45504744; if( uuidSize < 37 ){ return -1; } nicList = MP_NIC_GetNICInfo(); if( nicList == NULL ){ return -1; } nicInfo = (MP_NIC_INFO*)SORT_LIST_GetItemByIndex(nicList, 0); #ifdef _WIN32 sprintf_s(uuid, uuidSize, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", key, deviceType, uniqueID, value, nicInfo->macAddressValue[0], nicInfo->macAddressValue[1], nicInfo->macAddressValue[2], nicInfo->macAddressValue[3], nicInfo->macAddressValue[4], nicInfo->macAddressValue[5] ); #else; sprintf(uuid, "%08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X", key, deviceType, uniqueID, value, nicInfo->macAddressValue[0], nicInfo->macAddressValue[1], nicInfo->macAddressValue[2], nicInfo->macAddressValue[3], nicInfo->macAddressValue[4], nicInfo->macAddressValue[5] ); #endif SORT_LIST_CloseHandle(&nicList); return 1; }
void UPNP_SSDP_NOTIFY_DEVICE_INFO_Delete(void* item) { UPNP_SSDP_NOTIFY_DEVICE_INFO* info = (UPNP_SSDP_NOTIFY_DEVICE_INFO*)item; if( info == NULL ){ return ; } if( info->uuid != NULL ){ free(info->uuid); } if( info->locationUri != NULL ){ free(info->locationUri); } SORT_LIST_CloseHandle(&info->urnList); free(item); }
void HTTP_REQUEST_HEADER_Delete(void* item) { HTTP_REQUEST_HEADER* info = (HTTP_REQUEST_HEADER*)item; if( info == NULL ){ return ; } if( info->method != NULL ){ free(info->method); } if( info->uri != NULL ){ free(info->uri); } if( info->version != NULL ){ free(info->version); } if( info->headerList != NULL ){ SORT_LIST_CloseHandle(&info->headerList); } free(item); }
int UPNP_SERVER_SendNotifyAlive(UPNP_SSDP_HANDLE_ITEM* handle, UPNP_SSDP_NOTIFY_DEVICE_INFO* devInfo) { int ret = 0; int urnCount = 0; char* urn = NULL; int i=0; int j=0; char sendMsg[2048] = ""; SORT_LIST_HANDLE nicList = NULL; int nicCount = 0; MP_NIC_INFO* nicInfo = NULL; SOCKET sock; struct sockaddr_in addr; struct sockaddr_in send_addr; int opt = 1; unsigned long ipAdrr = 0; int ttl = 3; char sendMsgFormat[] = "NOTIFY * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nCACHE-CONTROL: max-age = 1800\r\nLOCATION: http://%s:%d%s\r\nNT: %s\r\nNTS: ssdp:alive\r\nSERVER: %s\r\nUSN: %s\r\n\r\n"; char nt[512] = ""; char usn[512] = ""; char ua[128] = ""; if( handle == NULL || devInfo == NULL){ ret = -1; goto Err_End; } nicList = MP_NIC_GetNICInfo(); if( nicList == NULL ){ ret = -3; goto Err_End; } UPNP_UTIL_GetUserAgent(ua, sizeof(ua)); nicInfo = MP_NIC_INFO_New(); nicInfo->ipv4 = (char*)malloc(strlen("127.0.0.1")+1); nicInfo->name = (char*)malloc(strlen("Loop Back")+1); nicInfo->macAddress = (char*)malloc(strlen("00-00-00-00-00-00")+1); #ifdef _WIN32 strcpy_s(nicInfo->ipv4 , strlen("127.0.0.1")+1, "127.0.0.1"); strcpy_s(nicInfo->name , strlen("Loop Back")+1, "Loop Back"); strcpy_s(nicInfo->macAddress, strlen("00-00-00-00-00-00")+1, "00-00-00-00-00-00"); #else strcpy(nicInfo->ipv4 , "127.0.0.1"); strcpy(nicInfo->name , "Loop Back"); strcpy(nicInfo->macAddress , "00-00-00-00-00-00"); #endif memset(nicInfo->macAddressValue, 0, 6); SORT_LIST_AddItem(nicList, nicInfo->name, nicInfo); nicCount = SORT_LIST_GetCount(nicList); if( nicCount <= 0 ){ ret = -4; goto Err_End; } memset((char*)&send_addr, 0, sizeof(struct sockaddr_in)); send_addr.sin_family = AF_INET; send_addr.sin_addr.s_addr = inet_addr("239.255.255.250"); send_addr.sin_port = htons(1900); //見つかったNIC全てで送信 for( i=0; i<nicCount; i++ ){ nicInfo = (MP_NIC_INFO*)SORT_LIST_GetItemByIndex(nicList, i); ipAdrr = inet_addr(nicInfo->ipv4); memset((char*)&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.S_un.S_addr = ipAdrr; sock = socket(AF_INET, SOCK_DGRAM, 0); if( sock < 0 ){ continue; } if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) < 0 ){ closesocket(sock); continue; } if(setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (char *)&ipAdrr, sizeof(ipAdrr)) < 0){ closesocket(sock); continue; } if(setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) < 0){ closesocket(sock); continue; } //upnp:rootdevice memset(sendMsg, 0, 2048); #ifdef _WIN32 sprintf_s(usn, sizeof(usn), "uuid:%s::upnp:rootdevice", devInfo->uuid); sprintf_s(sendMsg, sizeof(sendMsg), sendMsgFormat, nicInfo->ipv4, devInfo->locationPort, devInfo->locationUri, "upnp:rootdevice", ua, usn ); #else sprintf(usn, "uuid:%s::upnp:rootdevice", devInfo->uuid); sprintf(sendMsg, sendMsgFormat, nicInfo->ipv4, devInfo->locationPort, devInfo->locationUri, "upnp:rootdevice", ua, usn ); #endif if( sendto(sock, sendMsg, (int)strlen(sendMsg), 0, (struct sockaddr *)&send_addr, sizeof(send_addr)) < 0 ){ closesocket(sock); continue; } //uuid:device-UUID memset(sendMsg, 0, 2048); #ifdef _WIN32 sprintf_s(nt, sizeof(usn), "uuid:%s", devInfo->uuid); sprintf_s(usn, sizeof(usn), "uuid:%s", devInfo->uuid); sprintf_s(sendMsg, sizeof(sendMsg), sendMsgFormat, nicInfo->ipv4, devInfo->locationPort, devInfo->locationUri, nt, ua, usn ); #else sprintf(nt, "uuid:%s", devInfo->uuid); sprintf(usn, "uuid:%s", devInfo->uuid); sprintf(sendMsg, sendMsgFormat, nicInfo->ipv4, devInfo->locationPort, devInfo->locationUri, nt, ua, usn ); #endif if( sendto(sock, sendMsg, (int)strlen(sendMsg), 0, (struct sockaddr *)&send_addr, sizeof(send_addr)) < 0 ){ closesocket(sock); continue; } //urn:schemas-upnp-org:device:deviceType:ver //urn:schemas-upnp-org:service:serviceType:ver urnCount = SORT_LIST_GetCount(devInfo->urnList); for( j=0; j<urnCount; j++ ){ urn = (char*)SORT_LIST_GetItemByIndex(devInfo->urnList, j); memset(sendMsg, 0, 2048); #ifdef _WIN32 sprintf_s(nt, sizeof(usn), "%s", urn); sprintf_s(usn, sizeof(usn), "uuid:%s::%s", devInfo->uuid, urn); sprintf_s(sendMsg, sizeof(sendMsg), sendMsgFormat, nicInfo->ipv4, devInfo->locationPort, devInfo->locationUri, nt, ua, usn ); #else sprintf(nt, "%s", urn); sprintf(usn, "uuid:%s::%s", devInfo->uuid, urn); sprintf(sendMsg, sendMsgFormat, nicInfo->ipv4, devInfo->locationPort, devInfo->locationUri, nt, ua, usn ); #endif if( sendto(sock, sendMsg, (int)strlen(sendMsg), 0, (struct sockaddr *)&send_addr, sizeof(send_addr)) < 0 ){ break; } } closesocket(sock); } Err_End: if( nicList != NULL){ SORT_LIST_CloseHandle(&nicList); } return ret; }
void UPNP_SERVER_SSDPMSearchMsg(UPNP_SSDP_RECV_PARAM* param, HTTP_REQUEST_HEADER* httpReqHeader, char* src) { UPNP_SSDP_RECV_PARAM* info = NULL; UPNP_SSDP_HANDLE_ITEM* handle = NULL; UPNP_MSEARCH_REQUEST_INFO* requestParam = NULL; SORT_LIST_HANDLE resDeviceList = NULL; HTTP_HEADER_FIELD_INFO* headerItem = NULL; UPNP_MSEARCH_RES_DEV_INFO* devInfo = NULL; int length = 0; int i=0; char nowTime[30] = ""; char resMsg[1024] = ""; char buff[256] = ""; SOCKET sendSock; char ua[128] = ""; info = (UPNP_SSDP_RECV_PARAM*)param; if( info == NULL ){ return ; } handle = (UPNP_SSDP_HANDLE_ITEM*)info->ssdpHandle; if( handle == NULL ){ return ; } if( handle->msearchCallBack == NULL ){ return ; } requestParam = UPNP_MSEARCH_REQUEST_INFO_New(); resDeviceList = SORT_LIST_CreateHandle(1, SORT_LIST_COMPDEF_stricmp, NULL, UPNP_MSEARCH_RES_DEV_INFO_Delete); //リクエスト全体 length = (int)strlen(param->recvData); requestParam->res = (char*)malloc(length+1); #ifdef _WIN32 strcpy_s(requestParam->res, length+1, param->recvData); #else strcpy(requestParam->res, param->recvData); #endif //ヘッダをコピー headerItem = (HTTP_HEADER_FIELD_INFO*)SORT_LIST_FindItem(httpReqHeader->headerList, (void*)"HOST" ); if( headerItem != NULL ){ length = (int)strlen(headerItem->value); requestParam->host = (char*)malloc(length+1); #ifdef _WIN32 strcpy_s(requestParam->host, length+1, headerItem->value); #else strcpy(requestParam->host, headerItem->value); #endif } headerItem = (HTTP_HEADER_FIELD_INFO*)SORT_LIST_FindItem(httpReqHeader->headerList, (void*)"MAN" ); if( headerItem != NULL ){ length = (int)strlen(headerItem->value); requestParam->man = (char*)malloc(length+1); #ifdef _WIN32 strcpy_s(requestParam->man, length+1, headerItem->value); #else strcpy(requestParam->man, headerItem->value); #endif } headerItem = (HTTP_HEADER_FIELD_INFO*)SORT_LIST_FindItem(httpReqHeader->headerList, (void*)"MX" ); if( headerItem != NULL ){ length = (int)strlen(headerItem->value); requestParam->mx = (char*)malloc(length+1); #ifdef _WIN32 strcpy_s(requestParam->mx, length+1, headerItem->value); #else strcpy(requestParam->mx, headerItem->value); #endif } headerItem = (HTTP_HEADER_FIELD_INFO*)SORT_LIST_FindItem(httpReqHeader->headerList, (void*)"ST" ); if( headerItem != NULL ){ length = (int)strlen(headerItem->value); requestParam->st = (char*)malloc(length+1); #ifdef _WIN32 strcpy_s(requestParam->st, length+1, headerItem->value); #else strcpy(requestParam->st, headerItem->value); #endif } headerItem = (HTTP_HEADER_FIELD_INFO*)SORT_LIST_FindItem(httpReqHeader->headerList, (void*)"USER-AGENT" ); if( headerItem != NULL ){ length = (int)strlen(headerItem->value); requestParam->userAgent = (char*)malloc(length+1); #ifdef _WIN32 strcpy_s(requestParam->userAgent, length+1, headerItem->value); #else strcpy(requestParam->userAgent, headerItem->value); #endif } //通知 handle->msearchCallBack(requestParam, handle->msearchCallBackParam, resDeviceList); //MP_Sleep(500); MP_TIME_GetNowTime_RFC1123(nowTime, sizeof(nowTime)); //デバイスごとに送信 for(i=0; i<SORT_LIST_GetCount(resDeviceList); i++ ){ devInfo = (UPNP_MSEARCH_RES_DEV_INFO*)SORT_LIST_GetItemByIndex(resDeviceList, i); if( param->nicInfo->ipv4 == NULL || devInfo->uri == NULL ){ continue; } #ifdef _WIN32 strcpy_s(resMsg, sizeof(resMsg), "HTTP/1.1 200 OK\r\n"); sprintf_s(buff, sizeof(buff), "CACHE-CONTROL: max-age=%d\r\n", devInfo->max_age); strcat_s(resMsg, sizeof(resMsg), buff); // sprintf_s(buff, sizeof(buff), "DATE: %s\r\n", nowTime); // strcat_s(resMsg, sizeof(resMsg), buff); sprintf_s(buff, sizeof(buff), "LOCATION: http://%s:%d%s\r\n", param->nicInfo->ipv4, devInfo->port, devInfo->uri); strcat_s(resMsg, sizeof(resMsg), buff); sprintf_s(buff, sizeof(buff), "ST: %s\r\n", requestParam->st); strcat_s(resMsg, sizeof(resMsg), buff); if(devInfo->usn != NULL ){ sprintf_s(buff, sizeof(buff), "USN: %s\r\n", devInfo->usn); strcat_s(resMsg, sizeof(resMsg), buff); } UPNP_UTIL_GetUserAgent(ua, sizeof(ua)); sprintf_s(buff, sizeof(buff), "SERVER: %s\r\n", ua); strcat_s(resMsg, sizeof(resMsg), buff); strcat_s(resMsg, sizeof(resMsg), "EXT:\r\n"); strcat_s(resMsg, sizeof(resMsg), "\r\n"); #else strcpy(resMsg, "HTTP/1.1 200 OK\r\n"); sprintf(buff, "CACHE-CONTROL: max-age=%d\r\n", devInfo->max_age); strcat(resMsg, buff); // sprintf(buff, "DATE: %s\r\n", nowTime); // strcat(resMsg, buff); sprintf(buff, "LOCATION: http://%s:%d%s\r\n", param->nicInfo->ipv4, devInfo->port, devInfo->uri); strcat(resMsg, buff); sprintf(buff, "ST: %s\r\n", requestParam->st); strcat(resMsg, buff); if(devInfo->usn != NULL ){ sprintf(buff, "USN: %s\r\n", devInfo->usn); strcat(resMsg, buff); } UPNP_UTIL_GetUserAgent(ua, sizeof(ua)); sprintf_s(buff, sizeof(buff), "SERVER: %s\r\n", ua); strcat_s(resMsg, sizeof(resMsg), buff); strcat(resMsg, "EXT:\r\n"); strcat(resMsg, "\r\n"); #endif //レスポンス送信 MP_Sleep(10); sendSock = socket(AF_INET, SOCK_DGRAM, 0); //OutputDebugStringA(resMsg); sendto(sendSock, resMsg, (int)strlen(resMsg), 0, (struct sockaddr *)¶m->client, sizeof(param->client)); shutdown(sendSock, SD_BOTH); closesocket(sendSock); } SORT_LIST_CloseHandle(&resDeviceList); UPNP_MSEARCH_REQUEST_INFO_Delete(requestParam); }
int _UPNP_SERVER_StartSSDP(UPNP_SSDP_HANDLE_ITEM* handle) { int ret = 0; struct sockaddr_in addr; struct ip_mreq_source mreq; int opt = 1; SORT_LIST_HANDLE nicList = NULL; int listCount = 0; MP_NIC_INFO* nicInfo = NULL; int success = 0; int i=0; UPNP_SSDP_SOCKET_ITEM* sockItem = NULL; if( handle == NULL ){ return -1; } if( handle->ssdpSrvThread != NULL ){ return -2; } nicList = MP_NIC_GetNICInfo(); if( nicList == NULL ){ ret = -3; goto Err_End; } nicInfo = MP_NIC_INFO_New(); nicInfo->ipv4 = (char*)malloc(strlen("127.0.0.1")+1); nicInfo->name = (char*)malloc(strlen("Loop Back")+1); nicInfo->macAddress = (char*)malloc(strlen("00-00-00-00-00-00")+1); #ifdef _WIN32 strcpy_s(nicInfo->ipv4 , strlen("127.0.0.1")+1, "127.0.0.1"); strcpy_s(nicInfo->name , strlen("Loop Back")+1, "Loop Back"); strcpy_s(nicInfo->macAddress, strlen("00-00-00-00-00-00")+1, "00-00-00-00-00-00"); #else strcpy(nicInfo->ipv4 , "127.0.0.1"); strcpy(nicInfo->name , "Loop Back"); strcpy(nicInfo->macAddress , "00-00-00-00-00-00"); #endif memset(nicInfo->macAddressValue, 0, 6); SORT_LIST_AddItem(nicList, nicInfo->name, nicInfo); listCount = SORT_LIST_GetCount(nicList); if( listCount <= 0 ){ ret = -4; goto Err_End; } //見つかったNIC全てで受信できるようにする for( i=0; i<listCount; i++ ){ nicInfo = (MP_NIC_INFO*)SORT_LIST_GetItemByIndex(nicList, i); sockItem = UPNP_SSDP_SOCKET_ITEM_New(); sockItem->nicInfo = MP_NIC_INFO_Clone(nicInfo); //SSDP待ち受けポート(UDP 1900)の作成 sockItem->ssdpSock = socket(AF_INET, SOCK_DGRAM, 0); if( sockItem->ssdpSock < 0 ){ ret = -5; UPNP_SSDP_SOCKET_ITEM_Delete(sockItem); goto Err_End; } memset((char*)&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(1900); if( setsockopt(sockItem->ssdpSock, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) < 0 ){ ret = -6; UPNP_SSDP_SOCKET_ITEM_Delete(sockItem); goto Err_End; } if( bind(sockItem->ssdpSock, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){ ret = -7; UPNP_SSDP_SOCKET_ITEM_Delete(sockItem); goto Err_End; } memset(&mreq, 0, sizeof(mreq)); mreq.imr_interface.S_un.S_addr = INADDR_ANY; mreq.imr_sourceaddr.S_un.S_addr = inet_addr(nicInfo->ipv4); mreq.imr_multiaddr.S_un.S_addr = inet_addr("239.255.255.250"); if(setsockopt(sockItem->ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0){ UPNP_SSDP_SOCKET_ITEM_Delete(sockItem); }else{ SORT_LIST_AddItem(handle->ssdpSockList, sockItem->nicInfo->name, sockItem); } } if( SORT_LIST_GetCount(handle->ssdpSockList) <= 0 ){ ret = -8; goto Err_End; } handle->ssdpSrvStopFlag = 0; handle->ssdpSrvThread = MP_THREAD_BegineThread(UPNP_SERVER_SSDPThread, handle); if( nicList != NULL){ SORT_LIST_CloseHandle(&nicList); } return 0; Err_End: if( nicList != NULL){ SORT_LIST_CloseHandle(&nicList); } SORT_LIST_Clear(handle->ssdpSockList); return ret; }