void ILibSSDPClient_OnData(ILibAsyncUDPSocket_SocketModule socketModule,char* buffer, int bufferLength, int remoteInterface, unsigned short remotePort, void *user, void *user2, int *PAUSE) { struct packetheader *packet; packet = ILibParsePacketHeader(buffer,0,bufferLength); if(packet==NULL) { return; } ILibReadSSDP(packet,remoteInterface,remotePort,(struct SSDPClientModule*)user); ILibDestructPacket(packet); }
int ILibWebServer_StreamHeader(struct ILibWebServer_Session *session, struct packetheader *header) { struct packetheader *hdr = ILibWebClient_GetHeaderFromDataObject(session->Reserved3); struct packetheader_field_node *n = header->FirstField; char *buffer; int bufferLength; int RetVal; while(n!=NULL) { if(n->FieldLength==14 && strncasecmp(n->Field,"Content-Length",14)==0) { break; } n = n->NextField; } if(!(hdr->VersionLength==3 && memcmp(hdr->Version,"1.0",3)==0)) { // Remove Content-Length and Chunk it! if(n!=NULL) { n->Field = "Transfer-Encoding"; n->FieldLength = 17; n->FieldData = "chunked"; n->FieldDataLength = 7; } else { ILibAddHeaderLine(header,"Transfer-Encoding",17,"chunked",7); } } else { // Check to see if they gave us a Content-Length if(n==NULL) { // Must Close Socket when done session->Reserved6=1; } } bufferLength = ILibGetRawPacket(header,&buffer); RetVal = ILibWebServer_Send_Raw(session,buffer,bufferLength,0,0); ILibDestructPacket(header); return(RetVal); }
int ILibWebServer_Send(struct ILibWebServer_Session *session, struct packetheader *packet) { char *buffer; int bufferSize; int RetVal = 0; session->Reserved4=1; bufferSize = ILibGetRawPacket(packet,&buffer); RetVal = ILibAsyncServerSocket_Send(session->Reserved1,session->Reserved2,buffer,bufferSize,0); if(RetVal==0) { // Completed Send RetVal = ILibWebServer_RequestAnswered(session); } ILibDestructPacket(packet); return(RetVal); }
void ILibReadSSDP(SOCKET ReadSocket, struct SSDPClientModule *module) { int bytesRead = 0; char* buffer = (char*)malloc(4096); struct sockaddr_in addr; int addrlen = sizeof(struct sockaddr_in); struct packetheader *packet; struct packetheader_field_node *node; struct parser_result* pnode; char* Location = NULL; char* UDN = NULL; int Timeout = 0; int Alive = 0; int OK; int rt; bytesRead = recvfrom(ReadSocket, buffer, 4096, 0, (struct sockaddr *) &addr, &addrlen); if(bytesRead<=0) { FREE(buffer); return; } packet = ILibParsePacketHeader(buffer,0,bytesRead); if(packet->Directive==NULL) { /* M-SEARCH Response */ if(packet->StatusCode==200) { node = packet->FirstField; while(node!=NULL) { if(strncasecmp(node->Field,"LOCATION",8)==0) { Location = (char*)MALLOC(node->FieldDataLength+1); memcpy(Location,node->FieldData,node->FieldDataLength); Location[node->FieldDataLength] = '\0'; } if(strncasecmp(node->Field,"CACHE-CONTROL",13)==0) { pnode = ILibParseString(node->FieldData, 0, node->FieldDataLength, "=", 1); pnode->LastResult->data[pnode->LastResult->datalength] = '\0'; Timeout = atoi(pnode->LastResult->data); ILibDestructParserResults(pnode); } if(strncasecmp(node->Field,"USN",3)==0) { pnode = ILibParseString(node->FieldData, 0, node->FieldDataLength, "::", 2); pnode->FirstResult->data[pnode->FirstResult->datalength] = '\0'; UDN = pnode->FirstResult->data+5; ILibDestructParserResults(pnode); } node = node->NextField; } if(module->FunctionCallback!=NULL) { module->FunctionCallback(module,UDN,-1,Location,Timeout,module->Reserved); } } } else { /* Notify Packet */ if(strncasecmp(packet->Directive,"NOTIFY",6)==0) { OK = 0; rt = 0; node = packet->FirstField; while(node!=NULL) { node->Field[node->FieldLength] = '\0'; if(strncasecmp(node->Field,"NT",2)==0 && node->FieldLength==2) { node->FieldData[node->FieldDataLength] = '\0'; if(strncasecmp(node->FieldData,module->DeviceURN,module->DeviceURNLength)==0) { OK = -1; } else if(strncasecmp(node->FieldData,"upnp:rootdevice",15)==0) { rt = -1; } else { break; } } if(strncasecmp(node->Field,"NTS",3)==0) { if(strncasecmp(node->FieldData,"ssdp:alive",10)==0) { Alive = -1; rt = 0; } else { Alive = 0; OK = 0; } } if(strncasecmp(node->Field,"USN",3)==0) { pnode = ILibParseString(node->FieldData, 0, node->FieldDataLength, "::", 2); pnode->FirstResult->data[pnode->FirstResult->datalength] = '\0'; UDN = pnode->FirstResult->data+5; ILibDestructParserResults(pnode); } if(strncasecmp(node->Field,"LOCATION",8)==0) { Location = (char*)MALLOC(node->FieldDataLength+1); memcpy(Location,node->FieldData,node->FieldDataLength); Location[node->FieldDataLength] = '\0'; } if(strncasecmp(node->Field,"CACHE-CONTROL",13)==0) { pnode = ILibParseString(node->FieldData, 0, node->FieldDataLength, "=", 1); pnode->LastResult->data[pnode->LastResult->datalength] = '\0'; Timeout = atoi(pnode->LastResult->data); ILibDestructParserResults(pnode); } node = node->NextField; } if((OK!=0 && Alive!=0) || (rt!=0 && Alive==0)) { if(module->FunctionCallback!=NULL) { module->FunctionCallback(module,UDN,Alive,Location,Timeout,module->Reserved); } } } } if(Location!=NULL) {FREE(Location);} ILibDestructPacket(packet); FREE(buffer); }
void ILibMiniWebServerProcessSocket(struct ILibMWSHTTPReaderObject *Reader) { int bytesReceived; int i; struct packetheader_field_node *node; char* CharStar; if(Reader->BodySize==0) { /* Still Reading Headers */ bytesReceived = recv(Reader->ClientSocket,Reader->Header+Reader->HeaderIndex,2048-Reader->HeaderIndex,0); if(bytesReceived==0) { if(Reader->PacketHeader!=NULL) {ILibDestructPacket(Reader->PacketHeader);} if(Reader->Body_MallocSize!=0) {FREE(Reader->Body);} Reader->Body = NULL; Reader->Body_MallocSize = 0; Reader->PacketHeader = NULL; closesocket(Reader->ClientSocket); Reader->ClientSocket = 0xFFFFFFFF; return; } Reader->HeaderIndex += bytesReceived; if(Reader->HeaderIndex>4) { /* Must have read at least 4 bytes to perform check */ for(i=0;i<(Reader->HeaderIndex - 3);i++) { if (Reader->Header[i] == '\r' && Reader->Header[i+1] == '\n' && Reader->Header[i+2] == '\r' && Reader->Header[i+3] == '\n') { /* Finished Header */ Reader->PacketHeader = ILibParsePacketHeader(Reader->Header,0,i+4); Reader->PacketHeader->ReceivingAddress = Reader->LocalIPAddress; Reader->BodySize = -1; Reader->Body_Read = 0; node = Reader->PacketHeader->FirstField; while(node!=NULL) { if(strncasecmp(node->Field,"CONTENT-LENGTH",14)==0) { CharStar = (char*)MALLOC(1+node->FieldDataLength); memcpy(CharStar,node->FieldData,node->FieldDataLength); CharStar[node->FieldDataLength] = '\0'; Reader->BodySize = atoi(CharStar); FREE(CharStar); break; } node = node->NextField; } if(Reader->BodySize!=-1) { if(Reader->BodySize!=0) { Reader->Body = (char*)MALLOC(Reader->BodySize); Reader->Body_MallocSize = Reader->BodySize; } else { Reader->Body = NULL; Reader->Body_MallocSize = 0; } } else { Reader->Body = (char*)MALLOC(4096); Reader->Body_MallocSize = 4096; } if(Reader->HeaderIndex>i+4 && Reader->BodySize!=0) { /* Part of the body is in here */ memcpy(Reader->Body,Reader->Header+i+4,Reader->HeaderIndex-(&Reader->Header[i+4]-Reader->Header)); Reader->Body_BeginPointer = 0; Reader->Body_EndPointer = Reader->HeaderIndex-(int)(&Reader->Header[i+4]-Reader->Header); Reader->Body_Read = Reader->Body_EndPointer; if(Reader->BodySize==-1 || Reader->Body_Read>=Reader->BodySize) { DEBUGSTATEMENT(printf("Close\r\n")); Reader->FunctionCallback(Reader,Reader->PacketHeader,Reader->Body,&Reader->Body_BeginPointer,Reader->Body_EndPointer - Reader->Body_BeginPointer,-1,Reader->user); while(Reader->Body_BeginPointer!=Reader->Body_EndPointer && Reader->Body_BeginPointer!=0) { memcpy(Reader->Body,Reader->Body+Reader->Body_BeginPointer,Reader->Body_EndPointer-Reader->Body_BeginPointer); Reader->Body_EndPointer = Reader->Body_EndPointer-Reader->Body_BeginPointer; Reader->Body_BeginPointer = 0; Reader->FunctionCallback(Reader,Reader->PacketHeader,Reader->Body,&Reader->Body_BeginPointer,Reader->Body_EndPointer,-1,Reader->user); } if(Reader->PacketHeader!=NULL) {ILibDestructPacket(Reader->PacketHeader);} if(Reader->Body_MallocSize!=0) {FREE(Reader->Body);} Reader->Body = NULL; Reader->Body_MallocSize = 0; Reader->PacketHeader = NULL; closesocket(Reader->ClientSocket); Reader->ClientSocket = 0xFFFFFFFF; } else { Reader->FunctionCallback(Reader,Reader->PacketHeader,Reader->Body,&Reader->Body_BeginPointer,Reader->Body_EndPointer - Reader->Body_BeginPointer,0,Reader->user); while(Reader->Body_BeginPointer!=Reader->Body_EndPointer && Reader->Body_BeginPointer!=0) { memcpy(Reader->Body,Reader->Body+Reader->Body_BeginPointer,Reader->Body_EndPointer-Reader->Body_BeginPointer); Reader->Body_EndPointer = Reader->Body_EndPointer-Reader->Body_BeginPointer; Reader->Body_BeginPointer = 0; Reader->FunctionCallback(Reader,Reader->PacketHeader,Reader->Body,&Reader->Body_BeginPointer,Reader->Body_EndPointer,0,Reader->user); } } } else { /* There is no body, but the packet is here */ Reader->Body_BeginPointer = 0; Reader->Body_EndPointer = 0; if(Reader->BodySize<=0) { Reader->FunctionCallback(Reader,Reader->PacketHeader,NULL,&Reader->Body_BeginPointer,0,-1,Reader->user); if(Reader->PacketHeader!=NULL) {ILibDestructPacket(Reader->PacketHeader);} if(Reader->Body_MallocSize!=0) {FREE(Reader->Body);} Reader->Body = NULL; Reader->Body_MallocSize = 0; Reader->PacketHeader = NULL; closesocket(Reader->ClientSocket); Reader->ClientSocket = 0xFFFFFFFF; } else { Reader->FunctionCallback(Reader,Reader->PacketHeader,NULL,&Reader->Body_BeginPointer,0,0,Reader->user); } } break; } } } } else { /* Reading Body Only */ if(Reader->Body_BeginPointer == Reader->Body_EndPointer) { Reader->Body_BeginPointer = 0; Reader->Body_EndPointer = 0; } else { if(Reader->Body_BeginPointer!=0) { Reader->Body_EndPointer = Reader->Body_BeginPointer; } } if(Reader->Body_EndPointer == Reader->Body_MallocSize) { Reader->Body_MallocSize += 4096; Reader->Body = (char*)realloc(Reader->Body,Reader->Body_MallocSize); } bytesReceived = recv(Reader->ClientSocket,Reader->Body+Reader->Body_EndPointer,Reader->Body_MallocSize-Reader->Body_EndPointer,0); Reader->Body_EndPointer += bytesReceived; Reader->Body_Read += bytesReceived; Reader->FunctionCallback(Reader, Reader->PacketHeader, Reader->Body+Reader->Body_BeginPointer, &Reader->Body_BeginPointer, Reader->Body_EndPointer - Reader->Body_BeginPointer, 0, Reader->user); while(Reader->Body_BeginPointer!=Reader->Body_EndPointer && Reader->Body_BeginPointer!=0) { memcpy(Reader->Body,Reader->Body+Reader->Body_BeginPointer,Reader->Body_EndPointer-Reader->Body_BeginPointer); Reader->Body_EndPointer = Reader->Body_EndPointer-Reader->Body_BeginPointer; Reader->Body_BeginPointer = 0; Reader->FunctionCallback(Reader,Reader->PacketHeader,Reader->Body,&Reader->Body_BeginPointer,Reader->Body_EndPointer,0,Reader->user); } if((Reader->BodySize!=-1 && Reader->Body_Read>=Reader->BodySize)||(bytesReceived==0)) { if(Reader->Body_BeginPointer == Reader->Body_EndPointer) { Reader->Body_BeginPointer = 0; Reader->Body_EndPointer = 0; } Reader->FunctionCallback(Reader, Reader->PacketHeader, Reader->Body, &Reader->Body_BeginPointer, Reader->Body_EndPointer, -1,Reader->user); if(Reader->PacketHeader!=NULL) {ILibDestructPacket(Reader->PacketHeader);} if(Reader->Body_MallocSize!=0) {FREE(Reader->Body);} Reader->Body = NULL; Reader->Body_MallocSize = 0; Reader->PacketHeader = NULL; closesocket(Reader->ClientSocket); Reader->ClientSocket = 0xFFFFFFFF; } if(Reader->Body_BeginPointer==Reader->Body_EndPointer) { Reader->Body_BeginPointer = 0; Reader->Body_EndPointer = 0; } } }
void DH_RequestResponse(ILibWebClient_StateObject WebStateObject,int InterruptFlag,struct packetheader *header,char *bodyBuffer,int *beginPointer,int endPointer,int done,void *user1,void *user2,int *PAUSE) { struct DHC_Data *data = (struct DHC_Data*)user1; enum DHC_Errors status; void *Abort = NULL; char *rangeResult; struct parser_result *pr; long total; char *contentFeatures; struct DLNAProtocolInfo *pi; ILibReaderWriterLock rwLock = NULL; struct packetheader *GetRequest = NULL; struct sockaddr_in dest; int needToIssueRange = 0; int needToIssueRealRequest = 0; int MustNotResume = 0; struct packetheader *req; char *temp; if(data==NULL) { // // We appeared to be in the wrong state, most likely received // some bad responses, so if we ignore it, we should recover. // return; } if((header==NULL && done!=0) || (header!=NULL && header->StatusCode!=200 && header->StatusCode!=206 && done!=0)) { fclose(data->f); if(header==NULL) { status = DHC_ERRORS_CONNECTION_FAILED_OR_ABORTED; } else { status = DHC_ERRORS_HTTP; } if(data->Callback!=NULL) { if(header!=NULL) { header->StatusData[header->StatusDataLength]=0; } data->Callback(data->TransferStatus, status, header==NULL?0:header->StatusCode, header==NULL?NULL:header->StatusData,data->user); } DH_DestroyTransferStatus(data->TransferStatus); if(data->ActualPacket!=NULL) { ILibDestructPacket(data->ActualPacket); } free(data); ILibWebClient_ResetUserObjects(WebStateObject,NULL, NULL); } else if(header!=NULL && (header->StatusCode==200 || header->StatusCode==206)) { if(data->ActualPacket!=NULL) { if(data->DoneProcessingContentFeatures==0) { data->DoneProcessingContentFeatures = 1; // // Determine if Range is supported, then do another Head Range Request // if(data->TransferStatus->Reserved4!=0 && data->TransferStatus->RequestToken!=NULL) { // // Abort... Nothing really to do, because at this point we already finished. // Only thing to do, is to not actually issue the request. // data->TransferStatus->RequestToken = NULL; } else { // // Transfer Mode wasn't specified // contentFeatures = ILibGetHeaderLine(header,"contentFeatures.dlna.org",24); if(contentFeatures!=NULL) { temp = ILibString_Cat("http-get:*:*:",13,contentFeatures,(int)strlen(contentFeatures)); pi = DLNAProtocolInfo_Parse(temp,(int)strlen(temp)); if(pi!=NULL) { if(pi->TM_B!=0) { DH_AddHeader_transferMode(data->ActualPacket,DH_TransferMode_Bulk); data->TransferMode = DH_TransferMode_Bulk; } else if(pi->TM_I!=0) { DH_AddHeader_transferMode(data->ActualPacket,DH_TransferMode_Interactive); data->TransferMode = DH_TransferMode_Interactive; } else if(pi->TM_S!=0) { DH_AddHeader_transferMode(data->ActualPacket,DH_TransferMode_Streaming); data->TransferMode = DH_TransferMode_Streaming; } needToIssueRange = pi->SupportsByteBasedSeek; DLNAProtocolInfo_Destruct(pi); } free(temp); } else { // // since the server didn't respond with a DLNA Content Features, then // most likely this is a plain Media Server, in which case, if it doesn't support range // it won't return an error, and it'll just ignore the header, so we can issue a range // request anyways. // needToIssueRange = 1; } if(needToIssueRange!=0) { // // Issue a Range Request // req = ILibCreateEmptyPacket(); ILibSetVersion(req,"1.1",3); ILibAddHeaderLine(req,"Host",4,ILibGetHeaderLine(data->ActualPacket,"Host",4),(int)strlen(ILibGetHeaderLine(data->ActualPacket,"Host",4))); ILibSetDirective(req,"HEAD",4,data->ActualPacket->DirectiveObj,data->ActualPacket->DirectiveObjLength); DH_AddHeader_Range(req,0,-1); memset(&dest,0,sizeof(struct sockaddr_in)); dest.sin_family = AF_INET; dest.sin_addr.s_addr = header->Source->sin_addr.s_addr; dest.sin_port = header->Source->sin_port; ILibReaderWriterLock_WriteLock(data->rwLock); switch(data->TransferMode) { case DH_TransferMode_Bulk: ILibWebClient_SetQosForNextRequest(data->manager,ILibAsyncSocket_QOS_BACKGROUND); break; case DH_TransferMode_Streaming: ILibWebClient_SetQosForNextRequest(data->manager,ILibAsyncSocket_QOS_AUDIO_VIDEO); break; } data->TransferStatus->RequestToken = data->token = ILibWebClient_PipelineRequest(data->manager,&dest,req,&DH_RequestResponse,data,NULL); ILibReaderWriterLock_WriteUnLock(data->rwLock); } else { // // Range is not supported, so just continue with making the request. // However, before we do, since range isn't supported, we need to make // sure that we aren't trying to resume. MustNotResume = 1; needToIssueRealRequest = 1; } } } else { // // Process the Range Response // rangeResult = ILibGetHeaderLine(header,"content-range",13); if(rangeResult!=NULL) { pr = ILibParseString(rangeResult,0,(int)strlen(rangeResult),"/",1); total = atol(pr->LastResult->data); ILibDestructParserResults(pr); total -= data->StartPosition; sem_wait(&(data->TransferStatus->syncLock)); data->TransferStatus->TotalBytesToBeReceived = total; sem_post(&(data->TransferStatus->syncLock)); } else { // // We couldn't get a range result, so we need to make sure // we don't try to do a resume. // MustNotResume = 1; } // // Continue with actually making the content request // needToIssueRealRequest = 1; } if(needToIssueRealRequest!=0 && !(data->TransferStatus->Reserved4!=0 && data->TransferStatus->RequestToken!=NULL)) { GetRequest = data->ActualPacket; data->ActualPacket = NULL; rwLock = (ILibReaderWriterLock)ILibWebClient_GetUser(data->manager); memset(&dest,0,sizeof(struct sockaddr_in)); dest.sin_family = AF_INET; dest.sin_addr.s_addr = header->Source->sin_addr.s_addr; dest.sin_port = header->Source->sin_port; if(MustNotResume!=0) { // // Range isn't supported, so we must not resume // if(data->StartPosition!=0) { data->StartPosition = 0; fseek(data->f,0,SEEK_SET); } } else if(data->StartPosition!=0) { DH_AddHeader_Range(GetRequest,data->StartPosition,-1); } ILibReaderWriterLock_WriteLock(rwLock); switch(data->TransferMode) { case DH_TransferMode_Bulk: ILibWebClient_SetQosForNextRequest(data->manager,ILibAsyncSocket_QOS_BACKGROUND); break; case DH_TransferMode_Streaming: ILibWebClient_SetQosForNextRequest(data->manager,ILibAsyncSocket_QOS_AUDIO_VIDEO); break; } data->TransferStatus->RequestToken = data->token = ILibWebClient_PipelineRequest(data->manager,&dest,GetRequest,&DH_RequestResponse,data,NULL); ILibReaderWriterLock_WriteUnLock(rwLock); } *beginPointer = endPointer; // Don't really need to do this, because it should always be zero return; } data->buffer = bodyBuffer; data->bufferLength = endPointer; *beginPointer = endPointer; data->GotContinue = done; if(endPointer!=0 || done) { *PAUSE = 1; } if(data->token!=NULL) { data->webState = ILibWebClient_GetStateObjectFromRequestToken(data->token); } if(data->TransferStatus->Reserved4!=0 && data->TransferStatus->RequestToken!=NULL) { // // Abort // Abort = data->TransferStatus->RequestToken; data->TransferStatus->RequestToken = NULL; ILibWebClient_CancelRequest(Abort); } else if(data->TransferStatus->RequestToken!=NULL) { if(endPointer>0 || done) { ILibThreadPool_QueueUserWorkItem(data->pool,data,&DH_Pool_RequestResponse); } } } }
DH_TransferStatus DHS_RespondWithLocalFile(struct ILibWebServer_Session *session, ILibThreadPool pool, struct packetheader *header, size_t buffer_size, const char *file_name, unsigned int supported_transfer_mode, const char *mime_type, const char *content_features, const char* ifo_uri, void *user_obj, DHS_OnResponseDone callback_response) { DH_TransferStatus retval = NULL; FILE *f; struct DH_Data *data = NULL; struct packetheader *resp = NULL; char *ifo, *cf = NULL; long RangeStart,RangeLength,FileLength; char len[255]; enum ILibWebClient_Range_Result RangeResult = 0; enum DH_TransferModes transferMode; if(session->done==0) { // // If the get request wasn't completely received yet, then we don't need to do anything yet // return NULL; } f = fopen(file_name,"rb"); if(f!=NULL) { data = (struct DH_Data*)malloc(sizeof(struct DH_Data)); memset(data,0,sizeof(struct DH_Data)); resp = ILibCreateEmptyPacket(); ILibSetVersion(resp,"1.1",3); fseek(f,0,SEEK_END); FileLength = ftell(f); fseek(f,0,SEEK_SET); cf = ILibGetHeaderLine(header,"getcontentFeatures.dlna.org",27); if(cf!= NULL && memcmp(cf, "1", 1)!=0) { ILibWebServer_Send_Raw(session,"HTTP/1.1 400 Bad Request\r\n\r\n",28,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } transferMode = DH_GetRequestedTransferMode(header); if( ((transferMode == DH_TransferMode_Bulk) || (transferMode == DH_TransferMode_Interactive)) && ((ILibGetHeaderLine(header,"TimeSeekRange.dlna.org",22)!=NULL) || (ILibGetHeaderLine(header,"PlaySpeed.dlna.org",18)!=NULL) || (ILibGetHeaderLine(header,"realTimeInfo.dlna.org",21)!=NULL) ) ) { ILibWebServer_Send_Raw(session,"HTTP/1.1 400 Bad Request\r\n\r\n",28,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } if(ILibGetHeaderLine(header,"Range",5)!=NULL) { RangeResult = ILibWebClient_Parse_Range(ILibGetHeaderLine(header,"Range",5),&RangeStart,&RangeLength,FileLength); switch(RangeResult) { case ILibWebClient_Range_Result_OK: fseek(f,RangeStart,SEEK_SET); data->BytesLeft = RangeLength; ILibSetStatusCode(resp,206,"Partial Content",15); DH_AddHeader_ContentRange(resp,RangeStart,(RangeStart+RangeLength)-1,FileLength); break; case ILibWebClient_Range_Result_INVALID_RANGE: ILibWebServer_Send_Raw(session,"HTTP/1.1 416 Invalid Range\r\n\r\n",30,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); break; case ILibWebClient_Range_Result_BAD_REQUEST: ILibWebServer_Send_Raw(session,"HTTP/1.1 400 Bad Request\r\n\r\n",28,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); break; } } else if(ILibGetHeaderLine(header,"TimeSeekRange.dlna.org",22)!=NULL) { ILibWebServer_Send_Raw(session,"HTTP/1.1 406 Time-based seek not supported\r\n\r\n",46,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } else if(ILibGetHeaderLine(header,"PlaySpeed.dlna.org",18)!=NULL) { ILibWebServer_Send_Raw(session,"HTTP/1.1 406 PlaySpeeds not supported\r\n\r\n",41,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } else { ILibSetStatusCode(resp,200,"OK",2); data->BytesLeft = FileLength; sprintf(len,"%ld",data->BytesLeft); ILibAddHeaderLine(resp,"Content-Length",14,len,(int)strlen(len)); ILibAddHeaderLine(resp,"Accept-Ranges",13,"bytes",5); } if(transferMode == DH_TransferMode_Unspecified && mime_type != NULL) { if(ILibString_StartsWith(mime_type, (int) strlen(mime_type), "video/", 6) != 0) { DH_AddHeader_transferMode(resp, DH_TransferMode_Streaming); } else if(ILibString_StartsWith(mime_type, (int) strlen(mime_type), "audio/", 6) != 0) { DH_AddHeader_transferMode(resp, DH_TransferMode_Streaming); } else if(ILibString_StartsWith(mime_type, (int) strlen(mime_type), "image/", 6) != 0) { DH_AddHeader_transferMode(resp, DH_TransferMode_Interactive); } } else if(!(transferMode & supported_transfer_mode)) { // // Specified transfer mode is not supported // ILibWebServer_Send_Raw(session,"HTTP/1.1 406 Not Acceptable\r\n\r\n",31,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } else { DH_AddHeader_transferMode(resp,transferMode); } data->callback_response = callback_response; data->f = f; data->header = header; data->session = session; data->pool = pool; data->TransferStatus = retval = DH_CreateNewTransferStatus(); data->TransferStatus->TotalBytesToBeSent = data->BytesLeft; data->user_object = user_obj; retval->ServerSession = session; session->OnDisconnect = &DH_Disconnect; if(content_features!=NULL) { ILibAddHeaderLine(resp,"contentFeatures.dlna.org",24,(char*) content_features,(int)strlen(content_features)); } if(mime_type!=NULL) { ILibAddHeaderLine(resp,"Content-Type",12,(char*)mime_type,(int)strlen(mime_type)); } else { ILibAddHeaderLine(resp,"Content-Type",12,(char*)DHS_DEFAULT_MIMETYPE,(int)strlen(DHS_DEFAULT_MIMETYPE)); } if(ifo_uri!=NULL) { ifo = (char*)malloc((int)strlen(ifo_uri)+25); sprintf(ifo,"ifoFileURI.dlna.org=\"%s\"",ifo_uri); ILibAddHeaderLine(resp,"PRAGMA",6,ifo,(int)strlen(ifo)); free(ifo); } ILibWebServer_StreamHeader(session,resp); if(header->DirectiveLength==4 && strncasecmp(header->Directive,"HEAD",4)==0) { ILibWebServer_StreamBody(session,NULL,0,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(data->f); data->f = NULL; DH_DestroyTransferStatus(data->TransferStatus); free(data); session->OnDisconnect = NULL; return(NULL); } else { lock_init(&(data->SendStatusLock),0,1); ILibThreadPool_QueueUserWorkItem(pool,data,&DH_Pool); } } else { // // Error opening file // ILibWebServer_Send_Raw(session,"HTTP/1.1 404 File Not Found\r\n\r\n",31,ILibAsyncSocket_MemoryOwnership_STATIC,1); } return retval; }