Пример #1
0
DH_TransferStatus DHC_IssuePostRequestFromFile(ILibWebClient_RequestManager request_manager, ILibThreadPool pool, const char* target_uri, const char *file_path, int resume_pos, enum DH_TransferModes requestedTransferMode, const char *mime_type, const char *content_features, void* user_obj, DHC_OnResponseDone callback_response)
{
	DH_TransferStatus RetVal;
	struct packetheader *h;
	struct sockaddr_in addr;
	char host[22];
	struct DHC_Data *data = NULL;
	FILE *f;
	long fileLength;

	char *Ip;
	char *Path;
	unsigned short Port;
	ILibReaderWriterLock rwLock = (ILibReaderWriterLock)ILibWebClient_GetUser(request_manager);

	if(rwLock==NULL)
	{
		rwLock = ILibReaderWriterLock_CreateEx(ILibWebClient_GetChain(request_manager));
		ILibWebClient_SetUser(request_manager,rwLock);
	}

	f = fopen(file_path,"rb");
	if(f==NULL)
	{
		//
		// Couldn't open file
		//
		return(NULL);
	}

	data = (struct DHC_Data*)malloc(sizeof(struct DHC_Data));
	memset(data,0,sizeof(struct DHC_Data));
	data->TransferMode = requestedTransferMode;
	data->f = f;
	data->user = user_obj;
	data->Callback = callback_response;
	data->pool = pool;

	data->buffer = (char*)malloc(DHC_READ_BLOCK_SIZE);
	data->bufferLength = DHC_READ_BLOCK_SIZE;

	RetVal = data->TransferStatus = DH_CreateNewTransferStatus();
	data->rwLock = rwLock;

	ILibParseUri((char*)target_uri,&Ip,&Port,&Path);
	memset(&addr,0,sizeof(struct sockaddr_in));
	addr.sin_addr.s_addr = inet_addr(Ip);
	addr.sin_port = htons(Port);

	sprintf(host,"%s:%u",Ip,Port);

	h = ILibCreateEmptyPacket();
	ILibSetVersion(h,"1.1",3);
	ILibSetDirective(h,"POST",4,Path,(int)strlen(Path));
	ILibAddHeaderLine(h,"Host",4,host,(int)strlen(host));
	ILibAddHeaderLine(h,"Expect",6,"100-Continue",12);
	if(resume_pos>0)
	{
		fseek(f,0,SEEK_END);
		fileLength = ftell(f);
		fseek(f,(long)resume_pos,SEEK_SET);
		DH_AddHeader_ContentRange(h,resume_pos,fileLength-1,fileLength);
	}
	if(requestedTransferMode!=DH_TransferMode_Unspecified)
	{
		DH_AddHeader_transferMode(h, DH_TransferMode_Bulk);
	}
	if(content_features!=NULL)
	{
		ILibAddHeaderLine(h,"contentFeatures.dlna.org",24,(char*) content_features,(int)strlen(content_features));
	}
	if(mime_type!=NULL)
	{
		ILibAddHeaderLine(h,"Content-Type",12,(char*)mime_type,(int)strlen(mime_type));
	}

	ILibReaderWriterLock_WriteLock(rwLock);
	switch(data->TransferMode)
	{
		case DH_TransferMode_Bulk:
			ILibWebClient_SetQosForNextRequest(request_manager,ILibAsyncSocket_QOS_BACKGROUND);
			break;
		case DH_TransferMode_Streaming:
			ILibWebClient_SetQosForNextRequest(request_manager,ILibAsyncSocket_QOS_AUDIO_VIDEO);
			break;
	}
	data->token = data->TransferStatus->RequestToken = ILibWebClient_PipelineStreamedRequest(request_manager,&addr,h,&DHC_OnResponse,&DHC_OnSendOK,NULL,data);
	ILibReaderWriterLock_WriteUnLock(rwLock);

	free(Ip);
	free(Path);
	return(RetVal);
}
Пример #2
0
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;
}