/**********************************************************
*Filename: send_receive.c
*Author: 星云鹏
*Date: 2008-05-15
*
*消息、文件(夹)的发送和接收
*********************************************************/
#include "send_receive.h"
#include "ipmsg.h"
#include "users.h"
#include "coms.h"
#include <sys/utsname.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <pwd.h>
#include <sys/utsname.h>
#include <signal.h>
#include <pthread.h>
//////////////////////////////////////////////////
//发送udp包
void* sendMsg(command* com)
{
char buf[COMLEN];
int len, temp;
msgCreater(buf, com, sizeof(buf));
len = strlen(buf);
if (com->commandNo & IPMSG_FILEATTACHOPT)
{
temp = strlen(buf+len+1);
sendto(msgSock, buf, len+temp+2, 0,
(struct sockaddr*)&com->peer, sizeof(com->peer));
}
else sendto(msgSock, buf, len+1, 0,
(struct sockaddr*)&com->peer, sizeof(com->peer));
}
//////////////////////////////////////////////////
//聊天
int saySth()
{
char buf[100]; //临时输入区
char gMsg[MSGLEN];
command com;
user *cur=NULL;
int remainder; //扩展区剩余空间
int pos; //扩展区的当前输入位置
int who, temp, count;
int sended; //标记此包是否已经发过
user *pusers[50];
printf("\n*Talking mode\n"
"*Continuous Enter to send msg,\n"
"*Ctrl+D to quit conversation.\n");
pthread_mutex_lock(&usrMutex);
count = listUsers(pusers, &userList, sizeof(pusers)/sizeof(pusers[0]), 0);
pthread_mutex_unlock(&usrMutex);
who = inputNo(1, count, 1, "Please input user No.[1]:");
if (who>0)
{
cur = pusers[who-1];
initCommand(&com, IPMSG_SENDMSG|IPMSG_SENDCHECKOPT);
memcpy(&com.peer, &cur->peer, sizeof(com.peer));
remainder = MSGLEN;
pos = 0;
sended = 1;
while(1)
{
printf("(talking with %s):", cur->name);
if (fgets(buf, sizeof(buf), stdin)==NULL)
break;
if (buf[0] != '\n')
{
strncpy(com.additional+pos, buf, remainder);
temp = strlen(com.additional+pos);
pos += temp;
remainder -= temp;
sended = 0;
}
if ((buf[0]=='\n') || (remainder<=1))
{
if (!sended)
{
com.packetNo = (unsigned int)time(NULL);
sendMsg(&com);
sended = 1;
printf("Message sent.\n");
}
remainder = sizeof(com.additional);
pos = 0;
}
}
}
puts("\nEnd conversation.\n");
pthread_mutex_lock(&usrMutex);
unListUsers(pusers, count);
pthread_mutex_unlock(&usrMutex);
}
/////////////////////////////////////////////////
//文件发送
//选择要传输的文件
int selectFiles()
{
command com;
user *cur=NULL;
int who, count, flag, fileType;
unsigned int fileNo;
char fileName[FILENAME];
struct stat fileAttr;
char *strtmp;
filenode *fntmp, *head, *tail;
gsNode *newTask;
user *pusers[50];
printf("\n*Sending mode\n"
"*Continuous Enter to send file,\n"
"*Ctrl+D to quit.\n");
pthread_mutex_lock(&usrMutex);
count = listUsers(pusers, &userList, sizeof(pusers)/sizeof(pusers[0]), 0);
pthread_mutex_unlock(&usrMutex);
who = inputNo(1, count, 1, "Please input user No.[1]:");
if (who>0)
{
cur = pusers[who-1];
initCommand(&com, IPMSG_SENDMSG|IPMSG_FILEATTACHOPT);
memcpy(&com.peer, &cur->peer, sizeof(com.peer));
printf("To send file to %s(%s).\nPlease select file to send:\n", cur->name, cur->host);
newTask = (gsNode*)malloc(sizeof(gsNode));
initGsNode(newTask);
newTask->packetNo = com.packetNo;
fileNo = 0;
head = com.fileList;
tail = com.fileList;
while (1)
{
if (fgets(fileName, FILENAME, stdin) == NULL) //取消传输
{
free(newTask);
newTask = NULL;
while (head!=NULL)
{
tail = head;
head = head->next;
free(tail);
}
break;
}
transfStr(fileName, 0); //去除前后空白字符
if (fileName[0]=='\0')
break;
if (lstat(fileName, &fileAttr)<0)
{
printf("Get file attributes error.\n");
continue;
}
if (S_ISREG(fileAttr.st_mode))
fileType = 1;
else if (S_ISDIR(fileAttr.st_mode))
fileType = 2;
else
{
fileType = -1;
printf("Unsupported file type.\n");
continue;
}
if (tail == NULL)
head = tail = (filenode*)malloc(sizeof(filenode));
else
{
tail->next = (filenode*)malloc(sizeof(filenode));
tail = tail->next;
}
tail->next = NULL;
tail->fileNo = fileNo;
strncpy(tail->fileName, fileName, sizeof(tail->fileName));
snprintf(tail->fileSize, sizeof(tail->fileSize), "%x", fileAttr.st_size);
snprintf(tail->mtime, sizeof(tail->mtime), "%x", fileAttr.st_mtime);
tail->fileType = fileType;
fileNo++;
}
if (head==NULL)
{
if (newTask!=NULL)
free(newTask);
}
else
{
newTask->fileList.next = com.fileList = head;
pthread_mutex_lock(&sendFMutex); //lock
newTask->next = sendFHead.next;
sendFHead.next = newTask;
pthread_mutex_unlock(&sendFMutex); //unlock
if (newTask->fileList.next!=NULL)
{
sendMsg(&com); //可以放lock外面
printf("\nWaiting to transfer.\n");
}
}
}
pthread_mutex_lock(&usrMutex);
unListUsers(pusers, count);
pthread_mutex_unlock(&usrMutex);
}
//文件或文件夹发送
void* sendData(void* option)
{
int fSock = *(int *)option;
char buf[RECFRG], fileName[FILENAME];
int i, commandNo, realCount, offset, curErr;
unsigned int packetNo, fileNo;
filenode *preFile, *curFile;
gsNode *preSend, *curSend;
FILE* sfile;
sigset_t mask, oldmask;
free(option);
sigemptyset(&mask);
sigaddset(&mask, SIGPIPE);
if (pthread_sigmask(SIG_BLOCK, &mask, &oldmask) != 0)
printf("SIG_BLOCK error.\n");
//以tcp的方式接受传输请求
for (i=0;i<4;i++)
{
if (readDelimiter(fSock, buf, RECFRG, ':')<=0)
{
printf("Transfer cancelled.\n");
shutdown(fSock, SHUT_RDWR);
return NULL;
}
}
if (readDelimiter(fSock, buf, RECFRG, ':')<=0)
{
printf("Transfer cancelled.\n");
shutdown(fSock, SHUT_RDWR);
return NULL;
}
commandNo = atoi(buf);
if (!(commandNo & IPMSG_GETFILEDATA))
{
printf("Invalid request.\n");
shutdown(fSock, SHUT_RDWR);
return NULL;
}
if (readDelimiter(fSock, buf, RECFRG, ':')<=0)
{
printf("Transfer cancelled.\n");
shutdown(fSock, SHUT_RDWR);
return NULL;
}
sscanf(buf, "%x", &packetNo);
if (readDelimiter(fSock, buf, RECFRG, ':')<0)
{
printf("Transfer cancelled.\n");
shutdown(fSock, SHUT_RDWR);
return NULL;
}
sscanf(buf, "%x", &fileNo);
pthread_mutex_lock(&sendFMutex);
preSend = &sendFHead;
curSend = sendFHead.next;
while ((curSend != NULL) &&
(curSend->packetNo!=packetNo || curSend->transferring==1 ||
curSend->cancelled==1)){
preSend = preSend->next;
curSend = curSend->next;
}
if (curSend != NULL)
{
curSend->transferring = 1;
curSend->tcpSock = fSock;
pthread_mutex_unlock(&sendFMutex);
curFile = curSend->fileList.next;
preFile = &curSend->fileList;
while ((curFile!=NULL) && (curFile->fileNo!=fileNo))
{
preFile = preFile->next;
curFile = curFile->next;
}
if (curFile != NULL)
{
getFileName(fileName, curFile->fileName, sizeof(fileName));
printf("\nStart transferring %s.\n", fileName);
switch (curFile->fileType)
{
case 1: //发送文件
if (readDelimiter(fSock, buf, RECFRG, ':')<=0) //of