⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp_task.c

📁 蓝牙的spp dun ftp 功能的源代码
💻 C
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004-2006
Part of BlueLab 3.6.2-release

FILE NAME
    ftp_task.c
    
DESCRIPTION
    Source file for an OBEX Server application FTP Task.
*/


#include "ftps.h"
#include <message.h>
#include <vm.h>
#include <connection.h>
#include <pio.h>
#include <file.h>
#include <panic.h>
#include <stdlib.h>
#include <ps.h>

#include "ObexServer.h"

static void sendFolderListing(tFTPState *state, bool first);
static void sendGetObject(tFTPState *state, bool first);
static void setPathSubFolder(tFTPState *state, FTPS_SETPATH_SUBFOLDER_IND_T *msg);

static void ftp_handler(Task task, MessageId id, Message message)
{
	/* Get task control block */
	tFTPState *state = (tFTPState*)task;

	switch(id)
	{
	case FTPS_INIT_CFM:
	{
		FTPS_INIT_CFM_T *msg = (FTPS_INIT_CFM_T*)message;
		FTP_SVR_DEBUG(("FTPS_INIT_CFM :- "));
		if (msg->status == ftps_success)
		{
			GEN_DEBUG(("success\n"));
			state->session = msg->ftps;
		}
#ifdef FTPS_SVR_DEBUG
		else
		{
			if (msg->status == ftps_invalid_sdp)
			{
				GEN_DEBUG(("failure : Invalid SDP Record\n"));
			}
			else
			{
				GEN_DEBUG(("failure : %d\n", msg->status));
			}
		}
#endif
		break;
	}
	case FTPS_CONNECT_IND:
		{ /* Remote client has requested a connection */
		uint16 sz=0;
#ifdef FTPS_SVR_DEBUG
		FTPS_CONNECT_IND_T *msg = (FTPS_CONNECT_IND_T*)message;

		FTP_SVR_DEBUG(("FTPS_CONNECT_IND :-\n"));

		FTP_SVR_DEBUG(("            BD Addr : 0x%X 0x%X 0x%X%X\n", msg->bd_addr.nap, msg->bd_addr.uap, (uint16)(msg->bd_addr.lap>>16), (uint16)(msg->bd_addr.lap&0xFFFF)));
		FTP_SVR_DEBUG(("    Max. Packet Len : 0x%X (%d)\n", msg->maxPacketLen, msg->maxPacketLen));
#endif

		/* Get the maximum packet size from the PS and use it if it is bigger than the default (255) */
		PsRetrieve(PSKEY_FTPS_MAX_PACKET, &sz, sizeof(sz));
		sz = sz<FTPS_MAX_PACKET_SIZE ? FTPS_MAX_PACKET_SIZE:sz;


		FtpsConnectResponse(state->session, TRUE, sz, ftps_serv_readonly);
		break;
	}
	case FTPS_CONNECT_CFM:
		{ /* Connection process complete */
		FTPS_CONNECT_CFM_T *msg = (FTPS_CONNECT_CFM_T*)message;

		FTP_SVR_DEBUG(("FTPS_CONNECT_CFM :- "));
		if (msg->status == ftps_success)
		{
			GEN_DEBUG(("success\n"));
			FTP_SVR_DEBUG(("    Max. Packet Len : 0x%X (%d)\n", msg->maxPacketLen, msg->maxPacketLen));
			/* The actual max. packet size being used. ( minimum of client size and server size) */
			state->pktSize = msg->maxPacketLen;
			state->fileSrc = 0;
			state->currentDir = FILE_ROOT;
		}
		else
		{
			FTP_SVR_DEBUG(("failure : %d\n", msg->status));
		}
		break;
	}
	case FTPS_DISCONNECT_IND:
	{ /* Remote client has disconnected */
		FTP_SVR_DEBUG(("FTPS_DISCONNECT_IND\n"));
		break;
	}

	case FTPS_GETFOLDER_START_IND:
	{ /* Start to download the folder listing */
		FILE_INDEX file;

		FTP_SVR_DEBUG(("FTPS_GETFOLDER_START_IND\n"));

		file = FileFind(state->currentDir, folderFile, sizeof(folderFile)-1);

		if (file != FILE_NONE)
		{
			FTP_SVR_DEBUG(("      Sending Packet\n"));
			state->fileSrc = StreamFileSource(file);

			/* Send first packet to the client */
			sendFolderListing(state, TRUE);
		}
		else
		{ /* Not sure what to do here */
			FTP_SVR_DEBUG(("      Error Packet\n"));
		}

		break;
	}
	case FTPS_GETFOLDER_DATA_IND:
	{ /* Send the next packet of the folder listing to the remote client */
		FTP_SVR_DEBUG(("FTPS_GETFOLDER_DATA_IND\n"));

		if (state->fileSrc != 0)
		{
			sendFolderListing(state, FALSE);
		}
		else
			FtpsGetObjectReject(state->session, ftps_transfer_BadRequest);

		break;
	}

	case FTPS_GETOBJECT_COMPLETE_IND:
	case FTPS_GETFOLDER_COMPLETE_IND:
	{
		FTP_SVR_DEBUG(("FTPS_GETFOLDER_COMPLETE_IND or FTPS_GETOBJECT_COMPLETE_IND\n"));

		/* Object has been transfered, dispose of the source */
		StreamConnectDispose(state->fileSrc);
		state->fileSrc = 0;

		break;
	}

	case FTPS_SETPATH_SUBFOLDER_IND:
	{
		setPathSubFolder(state, (FTPS_SETPATH_SUBFOLDER_IND_T*)message);
		break;
	}
	case FTPS_SETPATH_ROOT_IND:
	{
		FTP_SVR_DEBUG(("FTPS_SETPATH_ROOT_IND\n"));
		if (state->currentDir == FILE_ROOT)
		{
			/* Should return ftps_setpath_AtRoot, but some stacks get confused, so just say 'OK' */
			FtpsSetPathRootResponse(state->session, ftps_setpath_OK);
		}
		else
		{
			state->currentDir = FILE_ROOT;
			FtpsSetPathRootResponse(state->session, ftps_setpath_OK);
		}
		break;
	}
	case FTPS_SETPATH_PARENT_IND:
	{
		FTP_SVR_DEBUG(("FTPS_SETPATH_PARENT_IND\n"));

		if (state->currentDir == FILE_ROOT)
		{
			FtpsSetPathParentResponse(state->session, ftps_setpath_AtRoot);
		}
		else
		{
			FILE_INDEX parent = FileParent(state->currentDir);
			if (parent == FILE_NONE)
			{  /* We are potentially in trouble if this happens, but it should 
						just be a case of 'belt and braces' */
				FtpsSetPathParentResponse(state->session, ftps_setpath_NotFound);
			}
			else
			{
				state->currentDir = parent;
				FtpsSetPathParentResponse(state->session, ftps_setpath_OK);
			}
		}
		break;
	}
	case FTPS_GETOBJECT_START_IND:
	{
		FTPS_GETOBJECT_START_IND_T *msg = (FTPS_GETOBJECT_START_IND_T*)message;
		const uint8* s=SourceMap(msg->src);
        uint16 cnt,end;
		char *name=NULL;
		uint16 pos = 0;

		FTP_SVR_DEBUG(("FTPS_GETOBJECT_START_IND\n"));
            
        if (msg->nameLen>0)
        {
			name = (char*)PanicUnlessMalloc(( msg->nameLen/2) );

            end=msg->nameOffset+msg->nameLen-2; /* UTF-16 Null */
#ifdef FTPS_SVR_DEBUG
            FTP_SVR_DEBUG(("     Filename : "));
            cnt=msg->nameOffset+1;
            while (cnt<end)
            {
                GEN_DEBUG(("%c",s[cnt]));
                cnt+=2;
            }
            GEN_DEBUG(("  -  "));
            cnt=msg->nameOffset;
            while (cnt<end)
            {
                GEN_DEBUG(("%X, ",s[cnt]));
                cnt+=1;
            }
            GEN_DEBUG(("\n"));
#endif
			/* Convert name to a narrow string.  Assume name is Latin-1 codepage UCS-16 */
			cnt=msg->nameOffset+1;
			while (cnt<end)
			{
				name[pos]=s[cnt];
				pos++;
				cnt+=2;
			}
        }
#ifdef FTPS_SVR_DEBUG
        if (msg->typeLen>0)
        {
            end=msg->typeOffset+msg->typeLen;
            FTP_SVR_DEBUG(("     Type : "));
            for (cnt=msg->typeOffset; cnt<end; cnt++)
                GEN_DEBUG(("%c, ",s[cnt]));
            GEN_DEBUG(("\n"));
        }
#endif

		/* We don't need the data in the source anymore, release it as soon as possible */
		FtpsPacketComplete(state->session);

		if (name == NULL)
			/* Server only supports get by name, not by type */
			FtpsGetObjectReject(state->session, ftps_transfer_NotFound);
		else
		{
			FILE_INDEX file;

			file = FileFind(state->currentDir, name, pos);

			/* Don't need the name anymore so free it */
			free(name);

			if ((file == FILE_NONE) || (FileType(file) == FILE_TYPE_DIRECTORY))
			{ /* Don't support getting a directory */
				FtpsGetObjectReject(state->session, ftps_transfer_NotFound);
			}
			else
			{
				FTP_SVR_DEBUG(("      Sending Packet\n"));
				state->fileSrc = StreamFileSource(file);

				/* Send first packet of the object */
				sendGetObject(state, TRUE);
			}
		}
		break;
	}
	case FTPS_GETOBJECT_DATA_IND:
	{
		FTP_SVR_DEBUG(("FTPS_GETOBJECT_DATA_IND\n"));

		if (state->fileSrc != 0)
		{
			/* Drop the packet we have just sent from the source */
			SourceDrop(state->fileSrc, state->pktSize);
			/* Send next packet */
			sendGetObject(state, FALSE);
		}
		else
			FtpsGetObjectReject(state->session, ftps_transfer_BadRequest);

		break;
	}

	default:
		FTP_SVR_DEBUG(("Unhandled Message : %d , 0x%0X\n",id,id)); 
		break;
	}
}

void ftp_initTask(tFTPState *state)
{
	state->FtpTask.handler = ftp_handler;

	state->session = 0;

	state->connected = FALSE;
	state->shutdown = FALSE;
}

static void sendFolderListing(tFTPState *state, bool first)
{
	uint16 len = SourceSize(state->fileSrc);

	if (len <= state->pktSize)
	{ /* send last packet */
		FTP_SVR_DEBUG(("       Sending last packet\n"));
		if (first)
			FtpsGetFolderFirstPacketSource(state->session, len, state->fileSrc, len, TRUE);
		else
			FtpsGetFolderNextPacketSource(state->session, 
					len, state->fileSrc, TRUE);
	}
	else
	{ /* send next packet */
		FTP_SVR_DEBUG(("       Sending interim packet\n"));
		if (first)
			FtpsGetFolderFirstPacketSource(state->session, state->pktSize, state->fileSrc, 0, FALSE);
		else
			FtpsGetFolderNextPacketSource(state->session, 
					state->pktSize, state->fileSrc, FALSE);
	}
}

static void sendGetObject(tFTPState *state, bool first)
{
	uint16 len = SourceSize(state->fileSrc);

	if (len <= state->pktSize)
	{ /* Last Packet */
		FTP_SVR_DEBUG(("       Sending last packet\n"));
		if (first)
			FtpsGetObjectFirstPacketSource(state->session,
						0, NULL, /* Client should already know this */
						0, NULL, len,  state->fileSrc, len, TRUE);
		else
			FtpsGetObjectNextPacketSource(state->session, len, state->fileSrc, TRUE);
	}
	else
	{ /* Not last packet */
		FTP_SVR_DEBUG(("       Sending interim packet\n"));
		if (first)
			FtpsGetObjectFirstPacketSource(state->session,
						0, NULL, /* Client should already know this */
						0, NULL, state->pktSize, state->fileSrc, 0, FALSE);
		else
			FtpsGetObjectNextPacketSource(state->session, state->pktSize, state->fileSrc, FALSE);
	}
}

static void setPathSubFolder(tFTPState *state, FTPS_SETPATH_SUBFOLDER_IND_T *msg)
{
	const uint8* s=SourceMap(msg->src);
	char *name;
    uint16 cnt,end;
	uint16 pos = 0;
	FILE_INDEX file;

	FTP_SVR_DEBUG(("FTPS_SETPATH_SUBFOLDER\n"));

	name = (char*)PanicUnlessMalloc(( msg->nameLength/2) );

    if (msg->nameLength>0)
    {
        end=msg->nameOffset+msg->nameLength-2; /* UTF-16 Null */
#ifdef FTPS_SVR_DEBUG
        FTP_SVR_DEBUG(("     Folder name : "));
        cnt=msg->nameOffset+1;
        while (cnt<end)
        {
            GEN_DEBUG(("%c",s[cnt]));
            cnt+=2;
        }
        GEN_DEBUG(("\n"));
#endif /* FTPS_SVR_DEBUG */

		/* Convert name to a narrow string.  Assume name is Latin-1 codepage UCS-16 */
		cnt=msg->nameOffset+1;
		while (cnt<end)
		{
			name[pos]=s[cnt];
			pos++;
			cnt+=2;
		}
    }

	/* We don't need the data in the source anymore, release it as soon as possible */
	FtpsPacketComplete(state->session);

	file = FileFind(state->currentDir, name, pos);

	/* Don't need the name anymore so free it */
	free(name);

	if ((file == FILE_NONE) && (msg->create))
	{ /* Can't create folder since this is a read only file system */
        FTP_SVR_DEBUG(("     Rejecting create due to being read only\n"));

		FtpsSetPathSubFolderResponse(state->session, ftps_setpath_ReadOnly);
	}
	else
	{ /* Changing Directory */
		bool ok = FALSE;

		if ((file != FILE_NONE) && (FileType(file) == FILE_TYPE_DIRECTORY))
			ok = TRUE;

		if (ok)
		{
			FTP_SVR_DEBUG(("     Changing folder\n"));
			state->currentDir = file;
			FtpsSetPathSubFolderResponse(state->session, ftps_setpath_OK);
		}
		else
		{
			FTP_SVR_DEBUG(("     Can't find folder\n"));
			FtpsSetPathSubFolderResponse(state->session, ftps_setpath_NotFound);
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -