├── Makefile ├── coms.c ├── coms.h ├── encode.c ├── encode.h ├── ipmsg.h ├── main.c ├── send_receive.c ├── send_receive.h ├── users.c ├── users.h ├── utils.c └── utils.h /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -g 2 | objects = main.o users.o utils.o send_receive.o coms.o encode.o 3 | 4 | ipmsg: $(objects) 5 | gcc $(CFLAGS) -o ipmsg $(objects) -lpthread 6 | 7 | main.o: main.c coms.h users.h ipmsg.h send_receive.h 8 | gcc $(CFLAGS) -c $^ 9 | 10 | users.o: users.c users.h coms.h 11 | gcc $(CFLAGS) -c $^ 12 | 13 | utils.o: utils.c coms.h 14 | gcc $(CFLAGS) -c $^ 15 | 16 | send_receive.o: send_receive.c send_receive.h coms.h ipmsg.h users.h 17 | gcc $(CFLAGS) -c $^ 18 | 19 | coms.o: coms.c ipmsg.h coms.h 20 | gcc $(CFLAGS) -c $^ 21 | 22 | encode.o: encode.c 23 | gcc $(CFLAGS) -c $^ 24 | 25 | .PHONY: clean 26 | clean: 27 | rm -f ipmsg $(objects) *.gch 28 | cgch: 29 | rm -f *.gch 30 | -------------------------------------------------------------------------------- /coms.c: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | *Filename: coms.c 3 | *Author: 星云鹏 4 | *Date: 2008-05-15 5 | * 6 | *主要的数据结构、全局变量和包的解析与生成 7 | *********************************************************/ 8 | 9 | #include "ipmsg.h" 10 | #include "coms.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | const char allHosts[] = "255.255.255.255"; //广播用地址 19 | int msgSock; //消息 20 | int tcpSock; //文件 21 | struct passwd* pwd; 22 | struct utsname sysName; 23 | char workDir[FILENAME]; 24 | int utf8; 25 | 26 | gsNode sendFHead, getFHead; //发送和接收文件列表 27 | msgList mList; //接受到的消息列表 28 | 29 | pthread_mutex_t sendFMutex=PTHREAD_MUTEX_INITIALIZER; //发送文件 30 | pthread_mutex_t getFMutex=PTHREAD_MUTEX_INITIALIZER; //接收文件 31 | pthread_mutex_t msgMutex=PTHREAD_MUTEX_INITIALIZER; //消息队列 32 | pthread_mutex_t usrMutex=PTHREAD_MUTEX_INITIALIZER; //消息队列 33 | sem_t waitNonEmpty, waitNonFull; //消息列表信号量 34 | 35 | /*解析接受到的字符串*/ 36 | int msgParser(char *msg, int size, command* com)//, struct sockaddr_in *peer) 37 | { 38 | char *start; 39 | char *pos; 40 | char outStr[COMLEN]; 41 | int min; 42 | int index=0,colonCount, tmp; 43 | 44 | if ((msg==NULL)||(com==NULL)) 45 | return -1; 46 | 47 | if (utf8) 48 | { 49 | g2u(msg, size, outStr, sizeof(outStr)); 50 | start = outStr; 51 | } 52 | else start = msg; 53 | 54 | bzero(com, sizeof(command)); 55 | while (index<5) 56 | { 57 | pos = strchr(start, ':'); 58 | if (pos==NULL) 59 | break; 60 | 61 | colonCount=1; 62 | while(*(pos+1) == ':') 63 | { 64 | pos++; 65 | colonCount++; 66 | } 67 | if (colonCount % 2 == 0) //偶数个:表示不是分割符 68 | { 69 | start = pos+1; 70 | continue; 71 | } 72 | 73 | switch (index) 74 | { 75 | case 0: 76 | com->version = atoi(start); 77 | break; 78 | case 1: 79 | com->packetNo = atoi(start); 80 | break; 81 | case 2: 82 | min = sizeof(com->senderName)<(pos-start)?sizeof(com->senderName):(pos-start); 83 | memcpy(com->senderName, start, min); 84 | com->senderName[min]='\0'; 85 | break; 86 | case 3: 87 | min = sizeof(com->senderHost)<(pos-start)?sizeof(com->senderHost):(pos-start); 88 | memcpy(com->senderHost, start, min); 89 | com->senderHost[min]='\0'; 90 | break; 91 | case 4: 92 | com->commandNo = atoi(start); 93 | break; 94 | default: 95 | break; 96 | } 97 | start = pos+1; 98 | index++; 99 | } 100 | 101 | strncpy(com->additional, start, MSGLEN); 102 | if (com->commandNo & IPMSG_FILEATTACHOPT) 103 | { 104 | tmp = strlen(com->additional); 105 | com->fileList = getFilelist(start+tmp+1); 106 | } 107 | 108 | index++; 109 | 110 | return index; 111 | 112 | 113 | } 114 | 115 | /*生成要发送的message*/ 116 | int msgCreater(char* msg, command* com, size_t msgLen) 117 | { 118 | int len, curLen, tmp, fileNo; 119 | char fileName[FILENAME], dest[COMLEN]; 120 | filenode *curFile; 121 | 122 | if ((dest==NULL)||(com==NULL)) 123 | return -1; 124 | 125 | len = snprintf(dest, sizeof(dest), "%d:%d:%s:%s:%d:%s", 126 | com->version, 127 | com->packetNo, 128 | com->senderName, 129 | com->senderHost, 130 | com->commandNo, 131 | com->additional); 132 | tmp = sizeof(dest) - len - 1; 133 | if (com->commandNo & IPMSG_FILEATTACHOPT) 134 | { 135 | fileNo = 0; 136 | curFile = com->fileList; 137 | while ((curFile != NULL) && (tmp>0)) 138 | { 139 | if (getFileName(fileName, curFile->fileName, sizeof(fileName))<0) 140 | { 141 | printf("msgCreater: get fileName error.\n"); 142 | return -1; 143 | } 144 | 145 | addColon(fileName, sizeof(fileName)); 146 | 147 | 148 | if (curFile->fileType == 1) 149 | curLen = snprintf(dest+len+1, tmp, "%d:%s:%s:%s:1:\a", 150 | fileNo, fileName, curFile->fileSize, curFile->mtime); 151 | else if (curFile->fileType == 2) 152 | curLen = snprintf(dest+len+1, tmp, "%d:%s:%s:%s:2:\a", 153 | fileNo, fileName, curFile->fileSize, curFile->mtime); 154 | else 155 | { 156 | printf("Unsupported file type.\n"); 157 | continue; 158 | } 159 | fileNo++; 160 | curFile = curFile->next; 161 | len += curLen; 162 | tmp -= curLen; 163 | } 164 | 165 | } 166 | 167 | if (utf8) 168 | u2g(dest, sizeof(dest), msg, msgLen); 169 | else strncpy(msg, dest, msgLen); 170 | 171 | return 0; 172 | } 173 | 174 | //分析待接收文件列表 175 | /*comFiles格式为xx:xx:xx:\a*/ 176 | filenode* getFilelist(const char* comFiles) 177 | { 178 | char eachFile[NAMELEN]; 179 | const char *pos, *backsplash_a, *colon, *start; 180 | filenode *head=NULL, *tail=NULL; 181 | int index, colonCount=0, temp, min; 182 | 183 | assert((comFiles!=NULL)); 184 | 185 | start = comFiles; 186 | 187 | while (1) 188 | { 189 | backsplash_a = strchr(start, '\a'); 190 | if (backsplash_a==NULL) 191 | break; 192 | if (tail==NULL) 193 | head = tail = (filenode*)malloc(sizeof(filenode)); 194 | else 195 | { 196 | tail->next = (filenode*)malloc(sizeof(filenode)); 197 | tail = tail->next; 198 | } 199 | 200 | tail->next = NULL; 201 | 202 | index = 0; 203 | 204 | pos = start; 205 | while(1) 206 | { 207 | colon = memchr(pos, ':', backsplash_a - pos); 208 | if (colon == NULL) 209 | break; 210 | colonCount=1; 211 | while(*(colon+1) == ':') 212 | { 213 | colon++; 214 | colonCount++; 215 | } 216 | if (colonCount % 2 == 0) //偶数个:表示不是分割符 217 | { 218 | pos = colon+1; 219 | continue; 220 | } 221 | 222 | switch(index) 223 | { 224 | case 0: 225 | sscanf(start, "%x", &tail->fileNo); //sscanf遇到':'也会结束 226 | break; 227 | case 1: 228 | min = (sizeof(tail->fileName)-1)<(colon-start)?(sizeof(tail->fileName)-1):(colon-start); 229 | memcpy(tail->fileName, start, min); 230 | tail->fileName[min] = '\0'; 231 | delColon(tail->fileName, sizeof(tail->fileName));//:: ----> : 232 | break; 233 | case 2: 234 | min = (sizeof(tail->fileSize)-1)<(colon-start)?(sizeof(tail->fileSize)-1):(colon-start); 235 | memcpy(tail->fileSize, start, min); 236 | tail->fileSize[min] = '\0'; 237 | break; 238 | case 3: 239 | min = (sizeof(tail->mtime)-1)<(colon-start)?(sizeof(tail->mtime)-1):(colon-start); 240 | memcpy(tail->mtime, start, min); 241 | tail->mtime[min] = '\0'; 242 | break; 243 | case 4: 244 | sscanf(start, "%x", &tail->fileType); //sscanf遇到':'也会结束 245 | break; 246 | case 5: 247 | min = (sizeof(tail->otherAttrs)-1)<(colon-start)?(sizeof(tail->otherAttrs)-1):(colon-start); 248 | memcpy(tail->otherAttrs, start, min); 249 | tail->otherAttrs[min] = '\0'; 250 | break; 251 | default: 252 | break; 253 | } 254 | start = colon+1; 255 | pos = start; 256 | index++; 257 | } 258 | start = backsplash_a + 1; 259 | } 260 | return head; 261 | } 262 | 263 | //相关数据结构的初始化与清理 264 | void initCommand(command *com, unsigned int flag) 265 | { 266 | if (com == NULL) 267 | return; 268 | bzero(com, sizeof(command)); 269 | com->version = 1; 270 | com->packetNo = (unsigned int)time(NULL); 271 | strncpy(com->senderName, pwd->pw_name, sizeof(com->senderName)); 272 | strncpy(com->senderHost, sysName.nodename, sizeof(com->senderHost)); 273 | com->commandNo = flag; 274 | return; 275 | } 276 | 277 | void deCommand(command *com) //delete fileList 278 | { 279 | filenode *cur; 280 | cur = com->fileList; 281 | while (cur!=NULL) 282 | { 283 | com->fileList = cur->next; 284 | free(cur); 285 | cur = com->fileList; 286 | } 287 | com->fileList = NULL; 288 | } 289 | 290 | void initGsNode(gsNode *gs) 291 | { 292 | if (gs == NULL) 293 | return; 294 | bzero(gs, sizeof(gsNode)); 295 | gs->tcpSock = -1; 296 | gs->packetNo = -1; 297 | } 298 | 299 | void deGsNode(gsNode *gs) //delete fileList & tragetDir 300 | { 301 | filenode *curFile; 302 | if (gs == NULL) 303 | return; 304 | while ((curFile=gs->fileList.next)!=NULL) 305 | { 306 | gs->fileList.next = curFile->next; 307 | free(curFile); 308 | } 309 | if (gs->targetDir != NULL) 310 | free(gs->targetDir); 311 | } 312 | 313 | 314 | -------------------------------------------------------------------------------- /coms.h: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | *Filename: coms.h 3 | *Author: 星云鹏 4 | *Date: 2008-05-15 5 | * 6 | *主要的数据结构、全局变量和包的解析与生成 7 | *********************************************************/ 8 | 9 | 10 | #ifndef COMMAND_H 11 | #define COMMAND_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define NAMELEN 50 22 | #define MSGLEN 1000 23 | #define COMLEN 1500 24 | #define RECFRG 1448 25 | #define HSIZE 10 26 | #define FILENAME 128 27 | #define MSGLIMIT 100 28 | #define HL_HEADERSIZE 4 29 | #define HL_FILESIZE 9 30 | #define HL_FILETYPE 1 31 | #define HL_1416 11 32 | #define CAPACITY 50 33 | 34 | #define IMHELP \ 35 | "Commands: help(h) list(ls) talk(tk) sendfile(sf)\n"\ 36 | "Commands: getfile(gf) refresh(rf) ceaseSend(cs) quit(q)\n" 37 | 38 | typedef int (*Mysnd)(int, const char*, int, int); 39 | 40 | typedef struct filenode filenode; 41 | 42 | typedef struct command 43 | { 44 | unsigned int version; 45 | unsigned int packetNo; 46 | char senderName[NAMELEN]; 47 | char senderHost[NAMELEN]; 48 | unsigned int commandNo; 49 | char additional[MSGLEN]; 50 | struct sockaddr_in peer; 51 | filenode * fileList; 52 | struct command *next; 53 | }command; 54 | 55 | struct filenode //文件序号:文件名:大小(单位:字节):最后修改时间:文件属性 [: 附加属性=val1[,val2…][:附加信息=…]]:\a文件序号… 56 | { 57 | int tcpSock; 58 | unsigned int fileNo; 59 | char fileName[FILENAME]; 60 | char fileSize[NAMELEN]; 61 | char mtime[NAMELEN]; 62 | int fileType; 63 | char otherAttrs[2*NAMELEN]; 64 | struct filenode* next; 65 | }; 66 | 67 | typedef struct gsNode 68 | { 69 | int tcpSock; 70 | struct sockaddr_in peer; 71 | unsigned int packetNo; 72 | int transferring; 73 | int cancelled; 74 | char *targetDir; 75 | filenode fileList; 76 | struct gsNode *next; 77 | } gsNode; 78 | 79 | typedef struct msgList 80 | { 81 | command comHead; 82 | command *comTail; 83 | } msgList; 84 | 85 | 86 | extern const char allHosts[]; //广播用地址 87 | extern int msgSock; //消息 88 | extern int tcpSock; //文件 89 | extern struct passwd* pwd; 90 | extern struct utsname sysName; 91 | extern char workDir[FILENAME]; 92 | extern int utf8; //系统的LC_CTYPE 93 | 94 | extern gsNode sendFHead, getFHead; //发送和接收文件列表 95 | extern msgList mList; //接受到的消息列表 96 | 97 | extern pthread_mutex_t sendFMutex; //发送文件 98 | extern pthread_mutex_t getFMutex; //接收文件 99 | extern pthread_mutex_t msgMutex; //消息队列 100 | extern pthread_mutex_t usrMutex; //消息队列 101 | extern sem_t waitNonEmpty, waitNonFull; //消息列表信号量 102 | 103 | extern int msgParser(char *msg, int size, command* com); 104 | extern int msgCreater(char* msg, command* com, size_t msgLen); 105 | extern filenode* getFilelist(const char* comFiles); 106 | extern void initCommand(command *com, unsigned int flag); 107 | extern void deCommand(command *com); 108 | extern void initGsNode(gsNode *gs); 109 | extern void deGsNode(gsNode *gs); 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /encode.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sklvjz/ipmsg/fd21a7a05de8b0b3f6436e74c012c22a988664a1/encode.c -------------------------------------------------------------------------------- /encode.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern int code_convert(char *to_charset, char *from_charset, 4 | char *inbuf, int inlen, char *outbuf, int outlen); 5 | extern int u2g(char *inbuf, int inlen, char *outbuf, int outlen); 6 | extern int g2u(char *inbuf, size_t inlen, char *outbuf, size_t outlen); 7 | -------------------------------------------------------------------------------- /ipmsg.h: -------------------------------------------------------------------------------- 1 | /* @(#)Copyright (C) H.Shirouzu 1996-1998 ipmsg.h Ver1.34 */ 2 | 3 | #ifndef IPMSG_H 4 | #define IPMSG_H 5 | 6 | 7 | /* IP Messenger Communication Protocol version 1.0 define */ 8 | /* macro */ 9 | #define GET_MODE(command) (command & 0x000000ffUL) 10 | #define GET_OPT(command) (command & 0xffffff00UL) 11 | 12 | /* header */ 13 | #define IPMSG_VERSION 0x0001 14 | #define IPMSG_DEFAULT_PORT 0x0979 15 | 16 | /* command */ 17 | #define IPMSG_NOOPERATION 0x00000000UL 18 | 19 | #define IPMSG_BR_ENTRY 0x00000001UL 20 | #define IPMSG_BR_EXIT 0x00000002UL 21 | #define IPMSG_ANSENTRY 0x00000003UL 22 | #define IPMSG_BR_ABSENCE 0x00000004UL 23 | 24 | #define IPMSG_BR_ISGETLIST 0x00000010UL 25 | #define IPMSG_OKGETLIST 0x00000011UL 26 | #define IPMSG_GETLIST 0x00000012UL 27 | #define IPMSG_ANSLIST 0x00000013UL 28 | #define IPMSG_FILE_MTIME 0x00000014UL 29 | #define IPMSG_FILE_CREATETIME 0x00000016UL 30 | #define IPMSG_BR_ISGETLIST2 0x00000018UL 31 | 32 | #define IPMSG_SENDMSG 0x00000020UL 33 | #define IPMSG_RECVMSG 0x00000021UL 34 | #define IPMSG_READMSG 0x00000030UL 35 | #define IPMSG_DELMSG 0x00000031UL 36 | 37 | #define IPMSG_GETFILEDATA 0x00000060UL 38 | #define IPMSG_RELEASEFILES 0x00000061UL 39 | #define IPMSG_GETDIRFILES 0x00000062UL 40 | 41 | #define IPMSG_GETINFO 0x00000040UL 42 | #define IPMSG_SENDINFO 0x00000041UL 43 | 44 | #define IPMSG_GETABSENCEINFO 0x00000050UL 45 | #define IPMSG_SENDABSENCEINFO 0x00000051UL 46 | 47 | /* option for all command */ 48 | #define IPMSG_ABSENCEOPT 0x00000100UL 49 | #define IPMSG_SERVEROPT 0x00000200UL 50 | #define IPMSG_DIALUPOPT 0x00010000UL 51 | #define IPMSG_FILEATTACHOPT 0x00200000UL 52 | 53 | /* option for send command */ 54 | #define IPMSG_SENDCHECKOPT 0x00000100UL 55 | #define IPMSG_SECRETOPT 0x00000200UL 56 | #define IPMSG_BROADCASTOPT 0x00000400UL 57 | #define IPMSG_MULTICASTOPT 0x00000800UL 58 | #define IPMSG_NOPOPUPOPT 0x00001000UL 59 | #define IPMSG_AUTORETOPT 0x00002000UL 60 | #define IPMSG_RETRYOPT 0x00004000UL 61 | #define IPMSG_PASSWORDOPT 0x00008000UL 62 | #define IPMSG_NOLOGOPT 0x00020000UL 63 | #define IPMSG_NEWMUTIOPT 0x00040000UL 64 | #define IPMSG_NOADDLISTOPT 0x00080000UL 65 | 66 | /* file types for fileattach command */ 67 | #define IPMSG_FILE_REGULAR 0x00000001UL 68 | #define IPMSG_FILE_DIR 0x00000002UL 69 | #define IPMSG_FILE_RETPARENT 0x00000003UL // return parent directory 70 | 71 | #define HOSTLIST_DELIMIT "\a" 72 | #define HOSTLIST_DUMMY "\b" 73 | 74 | /* end of IP Messenger Communication Protocol version 1.0 define */ 75 | #define IPMSG_FILE_MTIME 0x00000014UL 76 | #define IPMSG_FILE_CREATETIME 0x00000016UL 77 | 78 | /* IP Messenger for Windows internal define */ 79 | #define IPMSG_REVERSEICON 0x0100 80 | #define IPMSG_TIMERINTERVAL 4000 81 | #define IPMSG_CLOCKTICK 500 82 | #define IPMSG_GETLIST_FINISH 0 83 | 84 | #define IPMSG_BROADCAST_TIMER 0x0101 85 | #define IPMSG_SEND_TIMER 0x0102 86 | #define IPMSG_DELETE_TIMER 0x0103 87 | #define IPMSG_LISTGET_TIMER 0x0104 88 | #define IPMSG_LISTGETRETRY_TIMER 0x0105 89 | #define IPMSG_ENTRY_TIMER 0x0106 90 | #define IPMSG_DUMMY_TIMER 0x0107 91 | 92 | #define IPMSG_RETRY_TIMES 4 93 | 94 | #define IPMSG_NICKNAME 1 95 | #define IPMSG_FULLNAME 2 96 | 97 | #define IPMSG_NAMESORT 0x00000000 98 | #define IPMSG_IPADDRSORT 0x00000001 99 | #define IPMSG_HOSTSORT 0x00000002 100 | #define IPMSG_NOGROUPSORTOPT 0x00000100 101 | #define IPMSG_ICMPSORTOPT 0x00000200 102 | #define IPMSG_NOKANJISORTOPT 0x00000400 103 | #define IPMSG_ALLREVSORTOPT 0x00000800 104 | #define IPMSG_GROUPREVSORTOPT 0x00001000 105 | #define IPMSG_SUBREVSORTOPT 0x00002000 106 | 107 | #if defined WIN32 || defined XWINDOW 108 | #define MAX_SOCKBUF 32768 109 | #else 110 | #define MAX_SOCKBUF 8192 111 | #endif 112 | #define MAX_UDPBUF 8192 113 | #define MAX_BUF 1024 114 | #define MAX_NAMEBUF 50 115 | #define MAX_LANGBUF 10 116 | #define MAX_LISTBUF (MAX_NAMEBUF * 3 + 50) 117 | 118 | #define HS_TOOLS "HSTools" 119 | #define IP_MSG "IPMsg" 120 | #define NO_NAME "no_name" 121 | #define URL_STR "://" 122 | #define MAILTO_STR "mailto:" 123 | #endif /* IPMSG_H */ 124 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | *Filename: main.c 3 | *Author: 星云鹏 4 | *Date: 2008-05-15 5 | * 6 | *主程序、各个线程 7 | *********************************************************/ 8 | 9 | 10 | #include "users.h" 11 | #include "ipmsg.h" 12 | #include "send_receive.h" 13 | #include "coms.h" 14 | #include 15 | #include 16 | #include 17 | 18 | extern void destroyer(); 19 | 20 | //用户输入 21 | void* interacter(void* option) 22 | { 23 | char com[20], *fileName; 24 | int count; 25 | 26 | while(1) 27 | { 28 | printf("\n(ipmsg):"); 29 | fgets(com, sizeof(com), stdin); 30 | 31 | transfStr(com, 1); //去掉开头结尾空白字符,变成全小写 32 | 33 | if (!strcmp(com, "list") || 34 | !strcmp(com, "ls")) 35 | { 36 | pthread_mutex_lock(&usrMutex); 37 | count = listUsers(NULL, &userList, 2, 1);//只是列出 38 | pthread_mutex_unlock(&usrMutex); 39 | } 40 | else if (!strcmp(com, "quit") || 41 | !strcmp(com, "q")) 42 | { 43 | logout(); 44 | destroyer(); 45 | exit(0); 46 | } 47 | else if (!strcmp(com, "refresh") || 48 | !strcmp(com, "rf")) 49 | { 50 | login(); 51 | pthread_mutex_lock(&usrMutex); 52 | count = listUsers(NULL, &userList, 2, 1);//只是列出 53 | pthread_mutex_unlock(&usrMutex); 54 | } 55 | else if (!strcmp(com, "talk") || 56 | !strcmp(com, "tk")) 57 | { 58 | saySth(); 59 | } 60 | else if (!strcmp(com, "sendfile") || 61 | !strcmp(com, "sf")) 62 | { 63 | selectFiles(); 64 | } 65 | else if (!strcmp(com, "getfile") || 66 | !strcmp(com, "gf")) 67 | { 68 | recvFiles(); 69 | } 70 | else if (!strcmp(com, "ceaseSend") || 71 | !strcmp(com, "cs")) 72 | { 73 | ceaseSend(); 74 | } 75 | else if (!strcmp(com, "help") || 76 | !strcmp(com, "h")) 77 | printf(IMHELP); 78 | } 79 | 80 | } 81 | 82 | //接收udp包 83 | void* receiver(void *option) 84 | { 85 | command *peercom; 86 | struct sockaddr_in peer; 87 | int mSock = *(int*)option, len; 88 | char buf[COMLEN]; 89 | 90 | while(1) 91 | { 92 | if (recvfrom(mSock, buf, sizeof(buf), 0, (struct sockaddr*)&peer, &len)<0) 93 | continue; 94 | peercom = (command*)malloc(sizeof(command)); 95 | bzero(peercom, sizeof(command)); 96 | msgParser(buf, sizeof(buf), peercom); 97 | memcpy(&peercom->peer, &peer, sizeof(peercom->peer)); 98 | 99 | sem_wait(&waitNonFull); 100 | pthread_mutex_lock(&msgMutex); 101 | 102 | mList.comTail->next = peercom; 103 | mList.comTail = peercom; 104 | 105 | sem_post(&waitNonEmpty); 106 | pthread_mutex_unlock(&msgMutex); 107 | } 108 | } 109 | 110 | //处理接收的udp包 111 | void* processor(void *option) 112 | { 113 | command *peercom, com; 114 | int comMode, comOpt, temp; 115 | int len; 116 | user *cur; 117 | filenode *head, *curFile; 118 | gsNode *preSend, *curSend, *curGet, *preGet; 119 | 120 | initCommand(&com, IPMSG_NOOPERATION); 121 | while(1) 122 | { 123 | sem_wait(&waitNonEmpty); 124 | pthread_mutex_lock(&msgMutex); 125 | 126 | peercom = mList.comHead.next; 127 | mList.comHead.next = mList.comHead.next->next; 128 | if (mList.comHead.next == NULL) 129 | mList.comTail = &mList.comHead; 130 | 131 | sem_post(&waitNonFull); 132 | pthread_mutex_unlock(&msgMutex); 133 | 134 | memcpy(&com.peer, &peercom->peer, sizeof(com.peer)); 135 | 136 | comMode = GET_MODE(peercom->commandNo); 137 | comOpt = GET_OPT(peercom->commandNo); 138 | 139 | if (comOpt & IPMSG_SENDCHECKOPT) 140 | { 141 | com.packetNo = (unsigned int)time(NULL); 142 | snprintf(com.additional, MSGLEN, "%d", peercom->packetNo); 143 | com.commandNo = IPMSG_RECVMSG; 144 | sendMsg(&com); //发送回应 145 | } 146 | 147 | switch (comMode) 148 | { 149 | case IPMSG_SENDMSG: //发送命令 150 | if (strlen(peercom->additional)>0) 151 | { 152 | printf("\nGet message from: %s(%s)\n", peercom->senderName, peercom->senderHost); 153 | puts(peercom->additional); 154 | } 155 | 156 | if (comOpt & IPMSG_FILEATTACHOPT) 157 | { 158 | printf("\nGet Files from: %s(%s).\nInput \"getfile(gf)\" to download.\n", 159 | peercom->senderName, peercom->senderHost); 160 | curGet = (gsNode*)malloc(sizeof(gsNode)); 161 | initGsNode(curGet); 162 | memcpy(&curGet->peer, &peercom->peer, sizeof(curGet->peer)); 163 | curGet->packetNo = peercom->packetNo; 164 | curGet->fileList.next = peercom->fileList; 165 | peercom->fileList = NULL; // 166 | 167 | preGet = &getFHead; 168 | pthread_mutex_lock(&getFMutex); 169 | while ((preGet->next!=NULL) && 170 | (preGet->next->packetNo!=curGet->packetNo)) 171 | preGet = preGet->next; 172 | 173 | if (preGet->next==NULL) 174 | preGet->next = curGet; 175 | 176 | pthread_mutex_unlock(&getFMutex); 177 | } 178 | 179 | break; 180 | case IPMSG_ANSENTRY: // 181 | cur = (user*)malloc(sizeof(user)); 182 | memcpy(&cur->peer, &peercom->peer, sizeof(cur->peer)); 183 | strncpy(cur->name, peercom->senderName, NAMELEN); 184 | strncpy(cur->host, peercom->senderHost, NAMELEN); 185 | strncpy(cur->nickname, peercom->additional, NAMELEN); 186 | cur->inUse = 0; 187 | cur->exit = 0; 188 | cur->next = NULL; 189 | pthread_mutex_lock(&usrMutex); //lock 190 | if (insertUser(&userList, cur)<0) 191 | free(cur); 192 | pthread_mutex_unlock(&usrMutex); //unlock 193 | break; 194 | case IPMSG_BR_ENTRY: 195 | com.packetNo = (unsigned int)time(NULL); 196 | com.commandNo = IPMSG_ANSENTRY;// 197 | strncpy(com.additional, pwd->pw_name, MSGLEN); 198 | sendMsg(&com); 199 | 200 | cur = (user*)malloc(sizeof(user)); 201 | memcpy(&cur->peer, &peercom->peer, sizeof(cur->peer)); 202 | strncpy(cur->name, peercom->senderName, NAMELEN); 203 | strncpy(cur->host, peercom->senderHost, NAMELEN); 204 | strncpy(cur->nickname, peercom->additional, NAMELEN); 205 | cur->inUse = 0; 206 | cur->exit = 0; 207 | cur->next = NULL; 208 | pthread_mutex_lock(&usrMutex); 209 | if (insertUser(&userList, cur)<0) 210 | free(cur); 211 | pthread_mutex_unlock(&usrMutex); 212 | break; 213 | case IPMSG_RECVMSG: 214 | // 215 | break; 216 | case IPMSG_RELEASEFILES: //应该验证一下peer 217 | preSend = &sendFHead; 218 | pthread_mutex_lock(&sendFMutex); 219 | curSend = sendFHead.next; 220 | while ((curSend!=NULL)&&(curSend->packetNo!=atoi(peercom->additional))) 221 | { 222 | preSend = preSend->next; 223 | curSend = curSend->next; 224 | } 225 | 226 | if (curSend!=NULL) 227 | { 228 | curSend->cancelled = 1; 229 | if (curSend->tcpSock>0) 230 | shutdown(curSend->tcpSock, SHUT_RDWR); 231 | } 232 | pthread_mutex_unlock(&sendFMutex); 233 | break; 234 | case IPMSG_BR_EXIT: 235 | pthread_mutex_lock(&usrMutex); 236 | delUser(&userList, peercom); 237 | pthread_mutex_unlock(&usrMutex); 238 | break; 239 | case IPMSG_NOOPERATION: 240 | // 241 | break; 242 | default: 243 | printf("\nno handle, %x\n", peercom->commandNo); 244 | break; 245 | } 246 | deCommand(peercom); 247 | free(peercom); 248 | peercom = NULL; 249 | } 250 | 251 | } 252 | 253 | //数据清理 254 | void destroyer() 255 | { 256 | gsNode *preSend, *curSend, *preGet, *curGet; 257 | filenode *curFile; 258 | user *curUsr, *preUsr; 259 | 260 | preSend = &sendFHead; 261 | pthread_mutex_lock(&sendFMutex); 262 | curSend = sendFHead.next; 263 | while (curSend!=NULL) 264 | { 265 | if ((curSend->cancelled == 1) && (curSend->transferring==0)) 266 | { 267 | preSend->next = curSend->next; 268 | deGsNode(curSend); 269 | free(curSend); 270 | } 271 | else preSend = preSend->next; 272 | 273 | curSend = preSend->next; 274 | } 275 | pthread_mutex_unlock(&sendFMutex); 276 | 277 | 278 | preGet = &getFHead; 279 | pthread_mutex_lock(&getFMutex); 280 | curGet = getFHead.next; 281 | while (curGet!=NULL) 282 | { 283 | if ((curGet->cancelled==1) &&(curGet->transferring==0)) 284 | { 285 | preGet->next = curGet->next; 286 | deGsNode(curGet); 287 | free(curGet); 288 | } 289 | else preGet = preGet->next; 290 | 291 | curGet = preGet->next; 292 | } 293 | pthread_mutex_unlock(&getFMutex); 294 | 295 | preUsr = &userList; 296 | pthread_mutex_lock(&usrMutex); 297 | curUsr = userList.next; 298 | while (curUsr!=NULL) 299 | { 300 | if ((curUsr->exit==1) && (curUsr->inUse==0)) 301 | { 302 | preUsr->next = curUsr->next; 303 | free(curUsr); 304 | } 305 | else preUsr = preUsr->next; 306 | 307 | curUsr = preUsr->next; 308 | 309 | } 310 | pthread_mutex_unlock(&usrMutex); 311 | } 312 | 313 | 314 | 315 | void* cleaner(void *option) 316 | { 317 | gsNode *preSend, *curSend, *preGet, *curGet; 318 | filenode *curFile; 319 | user *curUsr, *preUsr; 320 | 321 | while(1) 322 | { 323 | sleep(30); //半分钟一次 324 | destroyer(); 325 | } 326 | 327 | } 328 | 329 | //初始化udp和tcp 330 | int initSvr() 331 | { 332 | struct sockaddr_in server; 333 | char targetHost[NAMELEN]; 334 | const int on=1; 335 | 336 | msgSock = socket(AF_INET, SOCK_DGRAM, 0); //UDP for Msg 337 | 338 | tcpSock = socket(AF_INET, SOCK_STREAM, 0); //TCP for File 339 | 340 | server.sin_family = AF_INET; 341 | server.sin_port = htons(IPMSG_DEFAULT_PORT); 342 | server.sin_addr.s_addr = htonl(INADDR_ANY); 343 | 344 | if (setsockopt(msgSock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))<0) 345 | { 346 | printf("initSvr: Socket options set error.\n"); 347 | exit(1); 348 | } 349 | 350 | if (bind(msgSock, (struct sockaddr*)&server, sizeof(server))<0) 351 | { 352 | printf("initSvr: Udp socket bind error.\n"); 353 | exit(1); 354 | } 355 | 356 | if (bind(tcpSock, (struct sockaddr*)&server, sizeof(server))<0) 357 | { 358 | printf("initSvr: Tcp socket bind error.\n"); 359 | exit(1); 360 | } 361 | 362 | if (listen(tcpSock, 10)<0) 363 | { 364 | printf("initSvr: Tcp listen error.\n"); 365 | exit(1); 366 | } 367 | 368 | //printf("Commands: list(ls) talk(tk) sendfile(sf)\n" 369 | //"Commands: getfile(gf) refresh(rf) ceaseSend(cs) quit(q)\n"); 370 | printf(IMHELP); 371 | } 372 | 373 | int main (int argc, char *argv []) 374 | { 375 | pthread_t procer, recver, iter, fler, cler; 376 | int *fSock; 377 | int tmp; 378 | pthread_attr_t attr; 379 | 380 | uname(&sysName); 381 | pwd = getpwuid(getuid()); 382 | getcwd(workDir, sizeof(workDir)); 383 | 384 | utf8 = 0; 385 | if (setlocale(LC_CTYPE, "")) 386 | if (!strcmp(nl_langinfo(CODESET), "UTF-8")) 387 | utf8 = 1; 388 | 389 | initGsNode(&sendFHead); 390 | initCommand(&mList.comHead, IPMSG_NOOPERATION); 391 | mList.comTail = &mList.comHead; 392 | userList.next = NULL; 393 | sem_init(&waitNonEmpty, 0, 0); 394 | sem_init(&waitNonFull, 0, MSGLIMIT); 395 | 396 | initSvr(); 397 | pthread_create(&procer, NULL, &processor, &msgSock); 398 | pthread_create(&recver, NULL, &receiver, &msgSock); 399 | pthread_create(&iter, NULL, &interacter, NULL); 400 | pthread_create(&cler, NULL, &cleaner, NULL); 401 | login(); 402 | 403 | pthread_attr_init(&attr); 404 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 405 | while(1) 406 | { 407 | if ((tmp=accept(tcpSock, NULL, NULL))<0) 408 | printf("Tcp accept error.\n"); 409 | else 410 | { 411 | fSock = (int *)malloc(sizeof(int)); 412 | *fSock = tmp; 413 | pthread_create(&fler, &attr, &sendData, fSock); 414 | } 415 | 416 | } 417 | 418 | pthread_join(procer, NULL); 419 | pthread_join(recver, NULL); 420 | pthread_join(iter, NULL); 421 | pthread_join(cler, NULL); 422 | return 0; 423 | } 424 | 425 | -------------------------------------------------------------------------------- /send_receive.c: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | *Filename: send_receive.c 3 | *Author: 星云鹏 4 | *Date: 2008-05-15 5 | * 6 | *消息、文件(夹)的发送和接收 7 | *********************************************************/ 8 | 9 | #include "send_receive.h" 10 | #include "ipmsg.h" 11 | #include "users.h" 12 | #include "coms.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | ////////////////////////////////////////////////// 27 | //发送udp包 28 | void* sendMsg(command* com) 29 | { 30 | char buf[COMLEN]; 31 | int len, temp; 32 | 33 | msgCreater(buf, com, sizeof(buf)); 34 | len = strlen(buf); 35 | if (com->commandNo & IPMSG_FILEATTACHOPT) 36 | { 37 | temp = strlen(buf+len+1); 38 | 39 | sendto(msgSock, buf, len+temp+2, 0, 40 | (struct sockaddr*)&com->peer, sizeof(com->peer)); 41 | } 42 | else sendto(msgSock, buf, len+1, 0, 43 | (struct sockaddr*)&com->peer, sizeof(com->peer)); 44 | } 45 | 46 | ////////////////////////////////////////////////// 47 | //聊天 48 | int saySth() 49 | { 50 | char buf[100]; //临时输入区 51 | char gMsg[MSGLEN]; 52 | command com; 53 | user *cur=NULL; 54 | int remainder; //扩展区剩余空间 55 | int pos; //扩展区的当前输入位置 56 | int who, temp, count; 57 | int sended; //标记此包是否已经发过 58 | user *pusers[50]; 59 | 60 | printf("\n*Talking mode\n" 61 | "*Continuous Enter to send msg,\n" 62 | "*Ctrl+D to quit conversation.\n"); 63 | 64 | pthread_mutex_lock(&usrMutex); 65 | count = listUsers(pusers, &userList, sizeof(pusers)/sizeof(pusers[0]), 0); 66 | pthread_mutex_unlock(&usrMutex); 67 | 68 | who = inputNo(1, count, 1, "Please input user No.[1]:"); 69 | 70 | if (who>0) 71 | { 72 | cur = pusers[who-1]; 73 | 74 | initCommand(&com, IPMSG_SENDMSG|IPMSG_SENDCHECKOPT); 75 | memcpy(&com.peer, &cur->peer, sizeof(com.peer)); 76 | 77 | remainder = MSGLEN; 78 | pos = 0; 79 | sended = 1; 80 | 81 | while(1) 82 | { 83 | printf("(talking with %s):", cur->name); 84 | if (fgets(buf, sizeof(buf), stdin)==NULL) 85 | break; 86 | if (buf[0] != '\n') 87 | { 88 | strncpy(com.additional+pos, buf, remainder); 89 | temp = strlen(com.additional+pos); 90 | pos += temp; 91 | remainder -= temp; 92 | sended = 0; 93 | } 94 | 95 | if ((buf[0]=='\n') || (remainder<=1)) 96 | { 97 | if (!sended) 98 | { 99 | com.packetNo = (unsigned int)time(NULL); 100 | sendMsg(&com); 101 | sended = 1; 102 | printf("Message sent.\n"); 103 | } 104 | remainder = sizeof(com.additional); 105 | pos = 0; 106 | } 107 | 108 | } 109 | } 110 | 111 | puts("\nEnd conversation.\n"); 112 | 113 | pthread_mutex_lock(&usrMutex); 114 | unListUsers(pusers, count); 115 | pthread_mutex_unlock(&usrMutex); 116 | 117 | } 118 | 119 | ///////////////////////////////////////////////// 120 | //文件发送 121 | //选择要传输的文件 122 | 123 | int selectFiles() 124 | { 125 | command com; 126 | user *cur=NULL; 127 | int who, count, flag, fileType; 128 | unsigned int fileNo; 129 | char fileName[FILENAME]; 130 | struct stat fileAttr; 131 | char *strtmp; 132 | filenode *fntmp, *head, *tail; 133 | gsNode *newTask; 134 | user *pusers[50]; 135 | 136 | printf("\n*Sending mode\n" 137 | "*Continuous Enter to send file,\n" 138 | "*Ctrl+D to quit.\n"); 139 | 140 | pthread_mutex_lock(&usrMutex); 141 | count = listUsers(pusers, &userList, sizeof(pusers)/sizeof(pusers[0]), 0); 142 | pthread_mutex_unlock(&usrMutex); 143 | 144 | who = inputNo(1, count, 1, "Please input user No.[1]:"); 145 | 146 | if (who>0) 147 | { 148 | 149 | cur = pusers[who-1]; 150 | 151 | initCommand(&com, IPMSG_SENDMSG|IPMSG_FILEATTACHOPT); 152 | memcpy(&com.peer, &cur->peer, sizeof(com.peer)); 153 | 154 | printf("To send file to %s(%s).\nPlease select file to send:\n", cur->name, cur->host); 155 | 156 | newTask = (gsNode*)malloc(sizeof(gsNode)); 157 | initGsNode(newTask); 158 | newTask->packetNo = com.packetNo; 159 | 160 | fileNo = 0; 161 | head = com.fileList; 162 | tail = com.fileList; 163 | 164 | while (1) 165 | { 166 | if (fgets(fileName, FILENAME, stdin) == NULL) //取消传输 167 | { 168 | free(newTask); 169 | newTask = NULL; 170 | while (head!=NULL) 171 | { 172 | tail = head; 173 | head = head->next; 174 | free(tail); 175 | } 176 | break; 177 | } 178 | 179 | transfStr(fileName, 0); //去除前后空白字符 180 | 181 | if (fileName[0]=='\0') 182 | break; 183 | 184 | if (lstat(fileName, &fileAttr)<0) 185 | { 186 | printf("Get file attributes error.\n"); 187 | continue; 188 | } 189 | 190 | if (S_ISREG(fileAttr.st_mode)) 191 | fileType = 1; 192 | else if (S_ISDIR(fileAttr.st_mode)) 193 | fileType = 2; 194 | else 195 | { 196 | fileType = -1; 197 | printf("Unsupported file type.\n"); 198 | continue; 199 | } 200 | 201 | if (tail == NULL) 202 | head = tail = (filenode*)malloc(sizeof(filenode)); 203 | else 204 | { 205 | tail->next = (filenode*)malloc(sizeof(filenode)); 206 | tail = tail->next; 207 | } 208 | 209 | tail->next = NULL; 210 | tail->fileNo = fileNo; 211 | strncpy(tail->fileName, fileName, sizeof(tail->fileName)); 212 | snprintf(tail->fileSize, sizeof(tail->fileSize), "%x", fileAttr.st_size); 213 | snprintf(tail->mtime, sizeof(tail->mtime), "%x", fileAttr.st_mtime); 214 | tail->fileType = fileType; 215 | 216 | fileNo++; 217 | } 218 | 219 | if (head==NULL) 220 | { 221 | if (newTask!=NULL) 222 | free(newTask); 223 | } 224 | else 225 | { 226 | newTask->fileList.next = com.fileList = head; 227 | pthread_mutex_lock(&sendFMutex); //lock 228 | newTask->next = sendFHead.next; 229 | sendFHead.next = newTask; 230 | pthread_mutex_unlock(&sendFMutex); //unlock 231 | 232 | if (newTask->fileList.next!=NULL) 233 | { 234 | sendMsg(&com); //可以放lock外面 235 | printf("\nWaiting to transfer.\n"); 236 | } 237 | } 238 | } 239 | 240 | pthread_mutex_lock(&usrMutex); 241 | unListUsers(pusers, count); 242 | pthread_mutex_unlock(&usrMutex); 243 | 244 | } 245 | 246 | //文件或文件夹发送 247 | void* sendData(void* option) 248 | { 249 | int fSock = *(int *)option; 250 | char buf[RECFRG], fileName[FILENAME]; 251 | int i, commandNo, realCount, offset, curErr; 252 | unsigned int packetNo, fileNo; 253 | filenode *preFile, *curFile; 254 | gsNode *preSend, *curSend; 255 | FILE* sfile; 256 | sigset_t mask, oldmask; 257 | 258 | free(option); 259 | 260 | sigemptyset(&mask); 261 | sigaddset(&mask, SIGPIPE); 262 | if (pthread_sigmask(SIG_BLOCK, &mask, &oldmask) != 0) 263 | printf("SIG_BLOCK error.\n"); 264 | 265 | //以tcp的方式接受传输请求 266 | for (i=0;i<4;i++) 267 | { 268 | if (readDelimiter(fSock, buf, RECFRG, ':')<=0) 269 | { 270 | printf("Transfer cancelled.\n"); 271 | shutdown(fSock, SHUT_RDWR); 272 | return NULL; 273 | } 274 | } 275 | 276 | if (readDelimiter(fSock, buf, RECFRG, ':')<=0) 277 | { 278 | printf("Transfer cancelled.\n"); 279 | shutdown(fSock, SHUT_RDWR); 280 | return NULL; 281 | } 282 | 283 | commandNo = atoi(buf); 284 | 285 | if (!(commandNo & IPMSG_GETFILEDATA)) 286 | { 287 | printf("Invalid request.\n"); 288 | shutdown(fSock, SHUT_RDWR); 289 | return NULL; 290 | } 291 | 292 | 293 | if (readDelimiter(fSock, buf, RECFRG, ':')<=0) 294 | { 295 | printf("Transfer cancelled.\n"); 296 | shutdown(fSock, SHUT_RDWR); 297 | return NULL; 298 | } 299 | 300 | sscanf(buf, "%x", &packetNo); 301 | 302 | if (readDelimiter(fSock, buf, RECFRG, ':')<0) 303 | { 304 | printf("Transfer cancelled.\n"); 305 | shutdown(fSock, SHUT_RDWR); 306 | return NULL; 307 | } 308 | sscanf(buf, "%x", &fileNo); 309 | 310 | pthread_mutex_lock(&sendFMutex); 311 | 312 | preSend = &sendFHead; 313 | curSend = sendFHead.next; 314 | 315 | while ((curSend != NULL) && 316 | (curSend->packetNo!=packetNo || curSend->transferring==1 || 317 | curSend->cancelled==1)){ 318 | preSend = preSend->next; 319 | curSend = curSend->next; 320 | } 321 | 322 | if (curSend != NULL) 323 | { 324 | curSend->transferring = 1; 325 | curSend->tcpSock = fSock; 326 | pthread_mutex_unlock(&sendFMutex); 327 | 328 | curFile = curSend->fileList.next; 329 | preFile = &curSend->fileList; 330 | while ((curFile!=NULL) && (curFile->fileNo!=fileNo)) 331 | { 332 | preFile = preFile->next; 333 | curFile = curFile->next; 334 | } 335 | 336 | if (curFile != NULL) 337 | { 338 | getFileName(fileName, curFile->fileName, sizeof(fileName)); 339 | printf("\nStart transferring %s.\n", fileName); 340 | switch (curFile->fileType) 341 | { 342 | case 1: //发送文件 343 | if (readDelimiter(fSock, buf, RECFRG, ':')<=0) //offset似乎没用上 344 | { 345 | printf("Transfer cancelled.\n"); 346 | shutdown(fSock, SHUT_RDWR); 347 | return NULL; 348 | } 349 | sscanf(buf, "%x", &offset); 350 | 351 | sfile = fopen(curFile->fileName, "r"); 352 | 353 | while ((realCount = fread(buf, 1, RECFRG, sfile))>0) 354 | if (writen(fSock, buf, realCount)<0) 355 | { 356 | curErr = errno; 357 | break; 358 | } 359 | break; 360 | case 2: //发送文件夹 361 | curErr = traverseDir(fSock, curFile->fileName, sendDir); 362 | break; 363 | default: 364 | break; 365 | } 366 | } 367 | } 368 | else pthread_mutex_unlock(&sendFMutex); 369 | 370 | pthread_mutex_lock(&sendFMutex); 371 | if ((curSend!=NULL) && (curSend->cancelled==1)) 372 | { 373 | preSend->next = curSend->next; 374 | deGsNode(curSend); 375 | free(curSend); 376 | pthread_mutex_unlock(&sendFMutex); 377 | shutdown(fSock, SHUT_RDWR); 378 | printf("Transfer canceled.\n"); 379 | return NULL; 380 | } 381 | 382 | if ((curErr<0) || (errno == ECONNRESET) || (errno == EPIPE)) //error or connection reset by peer 383 | { 384 | if (curFile!=NULL) 385 | { 386 | curSend->transferring = 0; 387 | curSend->tcpSock = -1; 388 | } 389 | pthread_mutex_unlock(&sendFMutex); 390 | shutdown(fSock, SHUT_RDWR); 391 | printf("Peer needs retransfer.\n"); 392 | return NULL; 393 | } 394 | 395 | if (curFile!=NULL) 396 | { 397 | printf("\n%s is transferred.\n", fileName); 398 | preFile->next = curFile->next; 399 | free(curFile); 400 | } 401 | 402 | 403 | if (curSend!=NULL && curSend->fileList.next == NULL) 404 | { 405 | preSend->next = curSend->next; 406 | deGsNode(curSend); 407 | free(curSend); 408 | } 409 | else if (curSend!=NULL) 410 | { 411 | curSend->transferring = 0; 412 | curSend->tcpSock = -1; 413 | } 414 | pthread_mutex_unlock(&sendFMutex); 415 | 416 | shutdown(fSock, SHUT_RDWR); 417 | } 418 | 419 | //发送文件夹 420 | 421 | int sendDir(int fSock, const char* fullpath, int fileSize, int fileType) 422 | { 423 | char strtmp[FILENAME], strformat[50], strdata[RECFRG], fileName[FILENAME]; 424 | int tmp, headLen, packetNo; 425 | FILE *sf; 426 | 427 | if (getFileName(strtmp, fullpath, sizeof(strtmp)) < 0) 428 | { 429 | printf("\nFilename is too long.\n"); 430 | return -1; 431 | } 432 | 433 | addColon(strtmp, sizeof(strtmp)); 434 | if (utf8) 435 | u2g(strtmp, sizeof(strtmp), 436 | fileName, sizeof(fileName)); 437 | else strncpy(fileName, strtmp, sizeof(fileName)); 438 | 439 | headLen = (strlen(fileName)+1) + (HL_HEADERSIZE+1) + 440 | (HL_FILETYPE+1) + (HL_FILESIZE+1) + 2*(HL_1416+1); 441 | packetNo = (unsigned int)time(NULL); //简化了,属性值并不准确 442 | snprintf(strformat, sizeof(strformat), "%%0%dx:%%s:%%0%dx:%%0%dx:14=%%0%dx:16=%%0%dx:", 443 | HL_HEADERSIZE, HL_FILESIZE, HL_FILETYPE, HL_1416-3, HL_1416-3); 444 | 445 | tmp = snprintf(strdata, sizeof(strdata), strformat, 446 | headLen, fileName, fileSize, fileType, packetNo, packetNo); 447 | 448 | switch (fileType) 449 | { 450 | case 1: 451 | if ((sf = fopen(fullpath, "r")) == NULL) 452 | { 453 | printf("file open error.\n"); 454 | return -1; 455 | } 456 | if (writen(fSock, strdata, tmp)<0) 457 | return -1; 458 | while ((tmp = fread(strdata, 1, RECFRG, sf))>0) 459 | { 460 | if (writen(fSock, strdata, tmp)<0) 461 | return -1; 462 | } 463 | fclose(sf); 464 | break; 465 | case 2: 466 | 467 | //break; 468 | case 3: 469 | if (writen(fSock, strdata, tmp)<0) 470 | return -1; 471 | break; 472 | default: 473 | break; 474 | } 475 | return 0; 476 | } 477 | 478 | //遍历要发送的文件夹,利用上面的回掉函数发送 479 | int traverseDir(int fSock, char* fullpath, Mysnd snd) //FILENAME指定了fullpath的容量 480 | { 481 | struct stat fst; 482 | struct dirent *dirp; 483 | char *ptr; 484 | DIR *dp; 485 | int tmp; 486 | 487 | 488 | if (lstat(fullpath, &fst)<0) 489 | { 490 | printf("\nDir: get attributes error.\n"); 491 | return -1; 492 | } 493 | 494 | if (S_ISREG(fst.st_mode)) 495 | return snd(fSock, fullpath, fst.st_size, 1); 496 | else if (S_ISDIR(fst.st_mode)) 497 | { 498 | if (snd(fSock, fullpath, 0, 2)<0) 499 | return -1; 500 | } 501 | else return -1; 502 | 503 | tmp = strlen(fullpath); 504 | ptr = fullpath + tmp; 505 | 506 | *ptr++ = '/'; //tmp+1 507 | *ptr = '\0'; 508 | 509 | if ((dp=opendir(fullpath)) == NULL) 510 | { 511 | printf("\nDir: open error.\n"); 512 | return -1; 513 | } 514 | 515 | while ((dirp=readdir(dp)) != NULL) 516 | { 517 | if (strcmp(dirp->d_name, ".")==0 || 518 | strcmp(dirp->d_name, "..")==0) 519 | continue; 520 | 521 | strncpy(ptr, dirp->d_name, FILENAME-tmp-1); 522 | if (traverseDir(fSock, fullpath, snd)<0) 523 | return -1; 524 | } 525 | 526 | ptr[-1] = '\0'; //还原fullname 527 | snd(fSock, ".", 0, 3); 528 | if (closedir(dp) < 0) 529 | { 530 | printf("\nDir: close error.\n"); 531 | return -1; 532 | } 533 | return 0; 534 | } 535 | 536 | //列举待发送文件 537 | int listSFiles(gsNode **list, gsNode *gs, int size) 538 | { 539 | filenode *curFile; 540 | int tmp=0; 541 | 542 | while ((gs!=NULL)&&(tmpcancelled==0)) 545 | { 546 | *list++ = gs; 547 | tmp++; 548 | } 549 | gs = gs->next; 550 | } 551 | 552 | return tmp; 553 | 554 | } 555 | 556 | //取消文件传输 557 | int ceaseSend() 558 | { 559 | gsNode *gsList[CAPACITY], *cur; 560 | int tmp, index, count; 561 | char buf[FILENAME]; 562 | filenode *curFile; 563 | 564 | while(1) 565 | { 566 | pthread_mutex_lock(&sendFMutex); 567 | count = listSFiles(gsList, sendFHead.next, sizeof(gsList)/sizeof(gsList[0])-1); 568 | pthread_mutex_unlock(&sendFMutex); 569 | 570 | if (count == 0) 571 | return 0; 572 | else 573 | { 574 | printf("\n++++++++++++++++++++\n"); 575 | printf("Files to send:\n"); 576 | for(tmp=1;tmp<=count;tmp++) 577 | { 578 | printf("%d. ", tmp); 579 | curFile = (*(gsList+tmp-1))->fileList.next; 580 | while (curFile!=NULL) 581 | { 582 | printf("%s ", curFile->fileName); 583 | curFile = curFile->next; 584 | } 585 | printf("\n"); 586 | } 587 | printf("++++++++++++++++++++\n"); 588 | } 589 | 590 | index = inputNo(1, count, 1, 591 | "Which file(s) to cancel?(Ctrl+D to quit)\nNumber[1]:"); 592 | 593 | if (index<0) 594 | return -1; 595 | 596 | pthread_mutex_lock(&sendFMutex); 597 | (*(gsList+index-1))->cancelled = 1; 598 | if ((*(gsList+index-1))->tcpSock>=0) 599 | shutdown((*(gsList+index-1))->tcpSock, SHUT_RDWR); 600 | pthread_mutex_unlock(&sendFMutex); 601 | } 602 | } 603 | 604 | 605 | //////////////////////////////////////////////////// 606 | //文件接收 607 | //选择要接收的文件 608 | int recvFiles() 609 | { 610 | gsNode *gsList[CAPACITY], *cur; 611 | int tmp, index, count; 612 | char buf[FILENAME]; 613 | struct stat dirAttr; 614 | pthread_t gFile; 615 | filenode *curFile; 616 | pthread_attr_t attr; 617 | 618 | while(1) 619 | { 620 | pthread_mutex_lock(&getFMutex); 621 | count = listGFiles(gsList, getFHead.next, sizeof(gsList)/sizeof(gsList[0])-1); 622 | pthread_mutex_unlock(&getFMutex); 623 | 624 | if (count == 0) 625 | return -1; 626 | else 627 | { 628 | printf("\n++++++++++++++++++++\n"); 629 | printf("Files to get:\n"); 630 | for(tmp=1;tmp<=count;tmp++) 631 | { 632 | printf("%d. ", tmp); 633 | curFile = (*(gsList+tmp-1))->fileList.next; 634 | while (curFile!=NULL) 635 | { 636 | printf("%s ", curFile->fileName); 637 | curFile = curFile->next; 638 | } 639 | printf("\n"); 640 | } 641 | printf("++++++++++++++++++++\n"); 642 | } 643 | 644 | index = inputNo(1, count, 1, 645 | "Which file(s) to get?(Ctrl+D to quit)\nNumber[1]:"); 646 | 647 | if (index<0) 648 | return -1; 649 | 650 | while(1) 651 | { 652 | printf("Where do you want to save?(Ctrl+D to quit)\nTarget dir[.]:"); 653 | if (fgets(buf, sizeof(buf), stdin)==NULL) 654 | return -1; 655 | 656 | transfStr(buf, 0); //去除前后空白字符 657 | 658 | if (buf[0]=='\0') 659 | { 660 | buf[0]='.'; 661 | buf[1]='\0'; 662 | } 663 | 664 | if ((stat(buf, &dirAttr)<0) || 665 | !S_ISDIR(dirAttr.st_mode) || 666 | (access(buf, W_OK)<0)) 667 | printf("Invalid directory. Please input again.\n"); 668 | else break; 669 | } 670 | 671 | cur = *(gsList+index-1); 672 | tmp = strlen(buf); 673 | pthread_mutex_lock(&getFMutex); 674 | if (cur->cancelled == 0) 675 | { 676 | cur->targetDir = (char*)malloc(tmp+1); 677 | strncpy(cur->targetDir, buf, tmp+1); 678 | cur->transferring = 1; 679 | } 680 | pthread_mutex_unlock(&getFMutex); 681 | pthread_attr_init(&attr); 682 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 683 | pthread_create(&gFile, &attr, &getData, cur); 684 | } 685 | 686 | } 687 | 688 | //文件接收线程 689 | void* getData(void* option) 690 | { 691 | gsNode *gList = (gsNode *)option; 692 | filenode *head=&gList->fileList, *cur; 693 | int fileType, tmp; 694 | command com; 695 | 696 | printf("\nStart getting files.\n"); 697 | while((cur=head->next) != NULL) 698 | { 699 | fileType = cur->fileType & 0x03; 700 | switch (fileType) 701 | { 702 | case 1: 703 | tmp=getFile(cur, gList); 704 | break; 705 | case 2: 706 | tmp=getDir(cur, gList); 707 | break; 708 | default: 709 | tmp = -1; 710 | printf("\nUnsupported file type.\n%s fails to be transfered.\n", cur->fileName); 711 | break; 712 | } 713 | 714 | if (tmp<0) 715 | { 716 | initCommand(&com, IPMSG_RELEASEFILES); 717 | snprintf(com.additional, sizeof(com.additional), "%d", gList->packetNo); 718 | memcpy(&com.peer, &gList->peer, sizeof(com.peer)); 719 | sendMsg(&com); 720 | pthread_mutex_lock(&getFMutex); 721 | gList->cancelled = 1; 722 | gList->transferring = 0; 723 | pthread_mutex_unlock(&getFMutex); 724 | printf("\n%s fails to be transfered.\n", cur->fileName); 725 | return NULL; 726 | } 727 | 728 | printf("\n%s is transferred.\n", cur->fileName); 729 | head->next = cur->next; 730 | free(cur); 731 | } 732 | 733 | pthread_mutex_lock(&getFMutex); 734 | gList->cancelled = 1; //其实是已经完成 735 | gList->transferring = 0; 736 | pthread_mutex_unlock(&getFMutex); 737 | 738 | printf("File reception done.\n"); 739 | } 740 | 741 | //接收文件 742 | int getFile(void* option, gsNode *gList) 743 | { 744 | int sockfd, readBytes; 745 | char buf[COMLEN]; 746 | char recvs[RECFRG]; 747 | filenode *head = (filenode*)option; 748 | command com; 749 | struct sockaddr_in peer; 750 | long fileSize, offset=0; 751 | FILE* recvFile; 752 | 753 | initCommand(&com, IPMSG_GETFILEDATA); //Regular file 754 | snprintf(com.additional, MSGLEN, "%x:%x:%x", gList->packetNo, head->fileNo, offset); 755 | 756 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 757 | 758 | bzero(&peer, sizeof(peer)); 759 | peer.sin_family = AF_INET; 760 | peer.sin_port = htons(IPMSG_DEFAULT_PORT); 761 | memcpy(&peer.sin_addr, &gList->peer.sin_addr, sizeof(peer.sin_addr)); 762 | 763 | if (connect(sockfd, (struct sockaddr*)&peer, sizeof(peer))<0) 764 | { 765 | printf("File connect error.\n"); 766 | return -1; 767 | } 768 | 769 | msgCreater(buf, &com, sizeof(buf)); 770 | 771 | if (writen(sockfd, buf, strlen(buf)+1)<0) 772 | return -1; 773 | 774 | sscanf(head->fileSize, "%x", &fileSize); 775 | 776 | if ((recvFile = fopen(head->fileName, "w+")) == NULL) 777 | { 778 | printf("getFile: file create error.\n"); 779 | return -1; 780 | } 781 | 782 | while (fileSize>0) 783 | { 784 | readBytes = fileSize < RECFRG ? fileSize:RECFRG; 785 | if ((readBytes = readn(sockfd, recvs, readBytes))<0) //RECFRG 786 | { 787 | printf("getFile: data transfer error.\n"); 788 | return -1; 789 | } 790 | 791 | fwrite(recvs, 1, readBytes, recvFile); 792 | fileSize -= readBytes; 793 | } 794 | fclose(recvFile); 795 | 796 | close(sockfd); 797 | return 0; 798 | } 799 | 800 | //接收文件夹时分析,头部 801 | int parseHeader(filenode *pfn, char * recvs) 802 | { 803 | char *strhead, *strtmp, gMsg[FILENAME]; 804 | int i=0; 805 | 806 | strhead = recvs; 807 | while (i<3) //分析前3段 808 | { 809 | strtmp = strchr(strhead, ':'); 810 | if (strtmp == NULL) 811 | return -1; 812 | *strtmp = '\0'; 813 | 814 | switch (i) 815 | { 816 | case 0: 817 | 818 | strncpy(gMsg, strhead, sizeof(gMsg)); 819 | delColon(gMsg, sizeof(gMsg)); 820 | if (utf8) 821 | g2u(gMsg, sizeof(gMsg), 822 | pfn->fileName, sizeof(pfn->fileName)); 823 | else strncpy(pfn->fileName, gMsg, sizeof(pfn->fileName)); 824 | break; 825 | case 1: 826 | //sscanf(strhead, "%x", &pfn->fileSize); 827 | strncpy(pfn->fileSize, strhead, sizeof(pfn->fileSize)); 828 | break; 829 | case 2: 830 | sscanf(strhead, "%x", &pfn->fileType); 831 | break; 832 | //case 3: //进行了简化 833 | // strncpy(pfh->h14, strhead+3, sizeof(pfh->h14)); 834 | //break; 835 | //case 4: 836 | //strncpy(pfh->h16, strhead+3, sizeof(pfh->h16)); 837 | //break; 838 | default: 839 | break; 840 | } 841 | 842 | strhead = strtmp+1; 843 | i++; 844 | } 845 | 846 | strncpy(pfn->otherAttrs, strhead, sizeof(pfn->otherAttrs)); 847 | 848 | return 0; 849 | } 850 | 851 | //接收文件夹 852 | int getDir(void *option, gsNode *gList) 853 | { 854 | int sockfd, readBytes, headerSize, fileType, dirDepth=0, tmp; 855 | char buf[COMLEN], recvs[RECFRG], hSize[HSIZE], fullPath[2*FILENAME]; 856 | filenode *head = (filenode*)option, *cur, fn; 857 | command com; 858 | struct sockaddr_in peer; 859 | long offset=0, fileSize; 860 | FILE* recvFile; 861 | 862 | strncpy(fullPath, gList->targetDir, sizeof(fullPath)); 863 | 864 | initCommand(&com, IPMSG_GETDIRFILES); //Direcotry 865 | 866 | snprintf(com.additional, MSGLEN, "%x:%x:%x", gList->packetNo, head->fileNo, offset); 867 | 868 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 869 | 870 | bzero(&peer, sizeof(peer)); 871 | peer.sin_family = AF_INET; 872 | peer.sin_port = htons(IPMSG_DEFAULT_PORT); 873 | memcpy(&peer.sin_addr, &gList->peer.sin_addr, sizeof(peer.sin_addr)); 874 | 875 | if (connect(sockfd, (struct sockaddr*)&peer, sizeof(peer))<0) 876 | { 877 | printf("File connect error.\n"); 878 | return -1; 879 | } 880 | 881 | msgCreater(buf, &com, sizeof(buf)); 882 | 883 | if (writen(sockfd, buf, strlen(buf)+1)<0) 884 | return -1; 885 | 886 | do 887 | { 888 | tmp = strlen(fullPath); 889 | if (tmp+1>=sizeof(fullPath)) 890 | { 891 | printf("getDir: target directory is too lang.\n"); 892 | return -1; 893 | } 894 | if (fullPath[tmp-1]!='/') 895 | { 896 | fullPath[tmp] = '/'; 897 | fullPath[tmp+1] = '\0'; 898 | } 899 | 900 | readBytes = readDelimiter(sockfd, hSize, HSIZE, ':'); 901 | sscanf(hSize, "%x", &headerSize); 902 | if (headerSize<=0 || headerSize<=readBytes || headerSize>RECFRG) //保护、防止溢出 903 | return -1; 904 | readn(sockfd, recvs, headerSize-readBytes); 905 | recvs[headerSize-readBytes]='\0'; 906 | 907 | if (parseHeader(&fn, recvs)<0) 908 | { 909 | printf("getDir: Parse protocol failed.\n"); 910 | return -1; 911 | } 912 | 913 | switch (fn.fileType & 0x03) 914 | { 915 | case IPMSG_FILE_REGULAR: 916 | 917 | strncat(fullPath, fn.fileName, sizeof(fullPath)-tmp-1); 918 | if ((recvFile = fopen(fullPath, "w+")) == NULL) 919 | { 920 | printf("Open error.\n"); 921 | return -1; 922 | } 923 | 924 | sscanf(fn.fileSize, "%x", &fileSize); 925 | while (fileSize>0) 926 | { 927 | readBytes = fileSize < RECFRG ? fileSize:RECFRG; 928 | if ((readBytes = readn(sockfd, recvs, readBytes))<0) //RECFRG 929 | { 930 | printf("File read error.\n"); 931 | return -1; 932 | } 933 | 934 | fwrite(recvs, 1, readBytes, recvFile); 935 | fileSize -= readBytes; 936 | } 937 | fclose(recvFile); 938 | getParentPath(fullPath, sizeof(fullPath)); 939 | break; 940 | 941 | case IPMSG_FILE_DIR: 942 | strncat(fullPath, fn.fileName, sizeof(fullPath)-tmp-1); 943 | tmp = strlen(fullPath); 944 | if (tmp+1>=sizeof(fullPath)) 945 | { 946 | printf("getDir: target directory is too lang.\n" 947 | "Filename(%s) has been truncated.\n", fn.fileName); 948 | fullPath[tmp-1] = '/'; 949 | } 950 | else 951 | { 952 | fullPath[tmp] = '/'; 953 | fullPath[tmp+1] = '\0'; 954 | } 955 | 956 | if (mkdir(fullPath, S_IRUSR|S_IWUSR|S_IXUSR)) 957 | { 958 | printf("getDir: mkdir failed.\n"); 959 | return -1; 960 | } 961 | 962 | dirDepth++; 963 | break; 964 | 965 | case IPMSG_FILE_RETPARENT: 966 | getParentPath(fullPath, sizeof(fullPath)); 967 | dirDepth--; 968 | break; 969 | 970 | default: 971 | printf("Unsupported file type.\n"); 972 | break; 973 | } 974 | 975 | }while(dirDepth>0); 976 | 977 | //close(sockfd); 978 | shutdown(sockfd, SHUT_RDWR); 979 | return 0; 980 | } 981 | 982 | //列举待接收文件 983 | int listGFiles(gsNode **list, gsNode *gs, int size) 984 | { 985 | filenode *curFile; 986 | int tmp=0; 987 | 988 | while ((gs!=NULL)&&(tmptransferring==0)&&(gs->cancelled==0)) 991 | { 992 | *list++ = gs; 993 | tmp++; 994 | } 995 | gs = gs->next; 996 | } 997 | 998 | return tmp; 999 | 1000 | } 1001 | 1002 | 1003 | ///////////////////////////////////////////////// 1004 | //登录 1005 | int login() 1006 | { 1007 | command com; 1008 | 1009 | initCommand(&com, IPMSG_BR_ENTRY); 1010 | 1011 | com.peer.sin_family = AF_INET; 1012 | com.peer.sin_port = htons(IPMSG_DEFAULT_PORT); 1013 | 1014 | if (inet_pton(AF_INET, allHosts, &com.peer.sin_addr)<0) 1015 | printf("login: Ip error.\n"); 1016 | 1017 | strncpy(com.additional, pwd->pw_name, MSGLEN); 1018 | 1019 | sendMsg(&com); 1020 | 1021 | } 1022 | 1023 | //退出 1024 | int logout() 1025 | { 1026 | command com; 1027 | 1028 | initCommand(&com, IPMSG_BR_EXIT); 1029 | 1030 | com.peer.sin_family = AF_INET; 1031 | com.peer.sin_port = htons(IPMSG_DEFAULT_PORT); 1032 | 1033 | if (inet_pton(AF_INET, allHosts, &com.peer.sin_addr)<0) 1034 | printf("logout: error\n"); 1035 | 1036 | strncpy(com.additional, pwd->pw_name, MSGLEN); 1037 | 1038 | sendMsg(&com); 1039 | printf("Bye!\n"); 1040 | 1041 | } 1042 | -------------------------------------------------------------------------------- /send_receive.h: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | *Filename: send_receive.h 3 | *Author: 星云鹏 4 | *Date: 2008-05-15 5 | * 6 | *消息、文件(夹)的发送和接收 7 | *********************************************************/ 8 | 9 | #ifndef SEND_RECV_H 10 | #define SEND_RECV_H 11 | 12 | #include "coms.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | extern void* sendMsg(command* com); 22 | extern int saySth(); 23 | extern int selectFiles(); 24 | extern void* sendData(void* option); 25 | extern int sendDir(int fSock, const char* fullpath, int fileSize, int fileType); 26 | extern int traverseDir(int fSock, char* fullpath, Mysnd snd); 27 | extern int listSFiles(gsNode **list, gsNode *gs, int size); 28 | extern int ceaseSend(); 29 | extern int recvFiles(); 30 | extern void* getData(void* option); 31 | extern int getFile(void* option, gsNode *gList); 32 | extern int parseHeader(filenode *pfn, char * recvs); 33 | extern int getDir(void *option, gsNode *gList); 34 | extern int listGFiles(gsNode **list, gsNode *gs, int size); 35 | extern int login(); 36 | extern int logout(); 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /users.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sklvjz/ipmsg/fd21a7a05de8b0b3f6436e74c012c22a988664a1/users.c -------------------------------------------------------------------------------- /users.h: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | *Filename: utils.h 3 | *Author: 星云鹏 4 | *Date: 2008-05-15 5 | * 6 | *用户的处理 7 | *********************************************************/ 8 | 9 | #ifndef USERS_H 10 | #define USERS_H 11 | 12 | #include "coms.h" 13 | typedef struct user 14 | { 15 | struct sockaddr_in peer; 16 | char name[NAMELEN]; 17 | char host[NAMELEN]; 18 | char nickname[NAMELEN]; 19 | int inUse; 20 | int exit; 21 | struct user *next; 22 | } user; 23 | 24 | extern user userList; 25 | 26 | extern int insertUser(user *uList, user *target); 27 | extern void destroyUsers(user *uList); 28 | extern int listUsers(user **pusers, user *uList, int size, int flag); 29 | extern int unListUsers(user **pusers, int num); 30 | extern int delUser(user *uList, command *peercom); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /utils.c: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | *Filename: utils.c 3 | *Author: 星云鹏 4 | *Date: 2008-05-15 5 | * 6 | *与协议无关的若干函数 7 | *********************************************************/ 8 | 9 | 10 | #include "coms.h" 11 | #include "utils.h" 12 | #include 13 | 14 | ////////////////////////////////////////////// 15 | //读写 16 | ssize_t readn(int fd, void *buf, size_t count) 17 | { 18 | char *strtmp; 19 | ssize_t reval, realcount=0; 20 | strtmp = (char *)buf; 21 | 22 | while (count>0) 23 | { 24 | reval = read(fd, strtmp, count); 25 | if (reval<0) 26 | if (errno == EINTR) 27 | continue; 28 | else return -1; 29 | else if (reval>0) 30 | { 31 | count -= reval; 32 | strtmp += reval; 33 | realcount += reval; 34 | continue; 35 | } 36 | else break; 37 | } 38 | 39 | return realcount; 40 | } 41 | 42 | ssize_t readDelimiter(int fd, void *buf, ssize_t count, char ch) 43 | { 44 | char *strtmp, *buftmp=buf; 45 | ssize_t reval, realcount=0; 46 | strtmp = (char *)buf; 47 | 48 | while (realcount0) 56 | { 57 | realcount++; 58 | if (*strtmp++ == ch) 59 | break; 60 | 61 | continue; 62 | } 63 | else break; 64 | } 65 | 66 | if (strtmp>buftmp) 67 | *(strtmp--) = '\0'; 68 | else *buftmp = '\0'; 69 | 70 | return realcount; 71 | } 72 | 73 | ssize_t writen(int fd, const void *buf, size_t count) 74 | { 75 | char *strtmp; 76 | ssize_t reval, realcount=count; 77 | strtmp = (char *)buf; 78 | 79 | while(count>0) 80 | { 81 | reval = write(fd, strtmp, count); 82 | if (reval < 0) 83 | if (errno == EINTR) 84 | continue; 85 | else return -1; 86 | 87 | count -= reval; 88 | strtmp += reval; 89 | } 90 | 91 | return realcount; 92 | } 93 | ssize_t readline(int fd, void *buf, int size) 94 | { 95 | char *strtmp; 96 | ssize_t reval, realcount=0; 97 | strtmp = (char *)buf; 98 | 99 | while(size>1) 100 | { 101 | reval = read(fd, strtmp, 1); 102 | if (reval<0) 103 | if (errno == EINTR) 104 | continue; 105 | else return -1; 106 | else if (reval == 0) 107 | break; 108 | else 109 | { 110 | realcount++; 111 | size--; 112 | if (*strtmp++ =='\n') 113 | break; 114 | } 115 | } 116 | *strtmp='\0'; 117 | return realcount; 118 | } 119 | 120 | ////////////////////////////////////////////// 121 | //处理: 122 | void delColon(char* dest, int size) //:: ---> : 123 | { 124 | char buf[FILENAME]; 125 | char *pd=dest, *pb=buf; 126 | int flag=0; 127 | 128 | while (*pb++ = *pd++) // = not == 129 | if ((*pd == ':') && (*(pd-1) == ':')) 130 | { 131 | pd++; 132 | flag = 1; 133 | } 134 | 135 | if (flag) 136 | strncpy(dest, buf, size); 137 | 138 | } 139 | 140 | void addColon(char* dest, int size) //: ---> :: 141 | { 142 | char buf[FILENAME], *pb, *pd; 143 | int flag=0; 144 | unsigned int tmp=0; 145 | pb = buf; 146 | pd = dest; 147 | while ((*pd != '\0')&&(tmpmax) 174 | return -1; 175 | 176 | if ((defmax)) 177 | def = min; 178 | 179 | while (1) 180 | { 181 | printf(prom); 182 | if (fgets(which, sizeof(which), stdin)==NULL) 183 | return -1; 184 | 185 | transfStr(which, 0); 186 | 187 | if (which[0]=='\0') 188 | { 189 | index = def; 190 | break; 191 | } 192 | 193 | tmp = strlen(which); 194 | 195 | if (which[tmp-1]=='\n') 196 | which[--tmp]='\0'; 197 | 198 | index = atoi(which); 199 | 200 | if (indexmax) 201 | printf("Invalid input. Please input again.\n"); 202 | else break; 203 | } 204 | return index; 205 | } 206 | 207 | ///////////////////////////////////////////// 208 | // 209 | int getFileName(char* dest, const char* fullpath, int size)//get filename from fullpath 210 | { 211 | char strtmp[128], *head; 212 | const char *tail; 213 | int tmp; 214 | tmp = strlen(fullpath); 215 | tail = fullpath + tmp - 1; 216 | while (*tail == '/') //去掉结尾所有的/ 217 | tail--; 218 | head = strtmp; 219 | while (tail>=fullpath && *tail!='/') //得到filename的倒序 220 | *head++ = *tail--; 221 | 222 | head--; 223 | while (size>0 && head>=strtmp) 224 | { 225 | *dest++ = *head--; 226 | size--; 227 | } 228 | if (size>0) 229 | { 230 | *dest = '\0'; 231 | return 0; // 232 | } 233 | else return -1; //文件名太长 234 | } 235 | 236 | 237 | int getParentPath(char *dest, int size) 238 | { 239 | char *last, *ptr; 240 | 241 | if (size<2) 242 | return -1; 243 | 244 | if ((last = strrchr(dest, '/'))==NULL) 245 | strncpy(dest, "./", size); 246 | else if (*(last+1)!='\0') 247 | *(last+1) = '\0'; 248 | else 249 | { 250 | ptr = last - 1; 251 | 252 | while (ptr>=dest) 253 | { 254 | if (*ptr=='/' && *(ptr+1)!='/') 255 | { 256 | *(ptr+1) = '\0'; 257 | break; 258 | } 259 | ptr--; 260 | } 261 | 262 | if (ptr dest) 286 | memmove(dest, ptr, len+1); 287 | 288 | ptr = dest+len-1; 289 | 290 | while (isspace(*ptr)) 291 | ptr--; 292 | 293 | *(ptr+1) = '\0'; 294 | 295 | ptr = dest; 296 | 297 | if (flag == 1) 298 | while (*ptr!='\0') 299 | { 300 | *ptr = tolower(*ptr); 301 | ptr++; 302 | } 303 | } 304 | 305 | -------------------------------------------------------------------------------- /utils.h: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | *Filename: utils.h 3 | *Author: 星云鹏 4 | *Date: 2008-05-15 5 | * 6 | *与协议无关的若干函数 7 | *********************************************************/ 8 | 9 | #ifndef UTIL_H 10 | #define UTIL_H 11 | 12 | #include 13 | 14 | extern ssize_t readn(int fd, void *buf, size_t count); 15 | extern ssize_t readDelimiter(int fd, void *buf, ssize_t count, char ch); 16 | extern ssize_t writen(int fd, const void *buf, size_t count); 17 | extern ssize_t readline(int fd, void *buf, int size); 18 | extern void delColon(char* dest, int size); 19 | extern void addColon(char* dest, int size); 20 | extern int inputNo(int min, int max, int def, char *prom); 21 | extern int getFileName(char* dest, const char* fullpath, int size); 22 | extern int getParentPath(char *dest, int size); 23 | extern void transfStr(char *dest, int flag); 24 | 25 | #endif 26 | --------------------------------------------------------------------------------