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

📄 tcp.c

📁 Linux下的飞鸽传书
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2006 Takeharu KATO * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <stdio.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/socket.h>#include <sys/ioctl.h> #include <netinet/in.h>#include <netinet/tcp.h> #include <netdb.h>#include <errno.h>#include <glib.h>#include <unistd.h>#include <glib.h>#include <libgnomevfs/gnome-vfs.h>#include "common.h"static intdestroy_tcp_connection(tcp_con_t *con) {  dbg_out("Here\n");  if (!con)    return -EINVAL;  if (con->self)    freeaddrinfo(con->self);  con->self=NULL;  close(con->soc);  return 0;}static intparse_request(request_msg_t *req,const char *request_string){  size_t len;  long int_val;  char *sp=NULL;  char *ep=NULL;  char *buffer;  ssize_t remains;  gboolean has_offset=FALSE;  int rc=0;  if  ( (!request_string) || (!req) )    return -EINVAL;  dbg_out("Here:%s\n",request_string);  buffer=g_strdup(request_string);  if (!buffer)    return -ENOMEM;  len=strlen(request_string);  _assert(len>0);  remains=len;  /*   * パケット番号   */  sp=buffer;  ep=memchr(sp, ':', remains);  if (!ep) {    rc=-EINVAL;    goto err_out;  }  *ep='\0';  remains =len - ((unsigned long)ep-(unsigned long)buffer);  if (remains<=0) {    rc=-EINVAL;    goto err_out;  }  ++ep;  int_val=strtol(sp, (char **)NULL, 16);  req->pkt_no=int_val;  dbg_out("pktno:%ld\n",req->pkt_no);  sp=ep;  /*   * ファイルID   */  ep=memchr(sp, ':', remains);  if (ep) {    has_offset=TRUE;    *ep='\0';    remains =len - ((unsigned long)ep-(unsigned long)buffer);    if (remains<=0) {      rc=-EINVAL;      goto err_out;    }    ++ep;  }  int_val=strtol(sp, (char **)NULL, 16);  req->fileid=int_val;  dbg_out("fileid:%d(%x)\n",req->fileid,req->fileid);  sp=ep;  /*   * オフセット   */  if (has_offset)    int_val=strtol(sp, (char **)NULL, 16);  else    int_val=0; /* 仮に0にする */  req->offset=int_val;  dbg_out("offset:%d(%x)\n",req->offset,req->offset);err_out:  g_free(buffer);  return rc;}static inttcp_ipmsg_finalize_connection(tcp_con_t *con){  int rc=0;  char dummy[1];  g_assert(con);  sock_set_buffer(con->soc);  dbg_out("Wait for closing by peer.\n");  sock_set_recv_timeout(con->soc,TCP_CLOSE_WAIT_SEC);  rc=wait_socket(con->soc,WAIT_FOR_READ,TCP_SELECT_SEC);  if (rc<0) {    dbg_out("OK timeout select :%s(%d)\n",strerror(errno),errno);    return -errno;  }  memset(dummy, 0, sizeof(dummy));  rc=recv(con->soc, dummy,sizeof(dummy),0); /* 相手のクローズ検出 */  if (rc<0)    dbg_out("OK timeout:%s(%d)\n",strerror(errno),errno);  else    rc=0;  return rc;}static inttcp_transfer_file(tcp_con_t *con,const char *path,const size_t size,off_t offset){  int fd;  int rc;  char buff[TCP_FILE_BUFSIZ];  ssize_t read_len;  ssize_t file_remains;  ssize_t soc_remains;  ssize_t write_len;  size_t total_write;  char *wp;  struct sigaction saved_act;  if ( (!con) || (!path) )    return -EINVAL;  fd=open(path,O_RDONLY);  if (fd<0)    return -errno;  rc=lseek(fd, offset, SEEK_SET);  if (rc<0) {    rc=-errno;    goto close_out;  }  total_write=0;  file_remains=size;  while(file_remains>0) {    read_len=read(fd,buff,TCP_FILE_BUFSIZ);    if (read_len<0) {      rc=-errno;      err_out("Can not read file %s %d\n",strerror(errno),errno);      goto close_out;    }    file_remains -= read_len;    soc_remains=read_len;    wp=buff;    if (wait_socket(con->soc,WAIT_FOR_WRITE,TCP_SELECT_SEC)<0) {      err_out("Can not send socket\n");      goto close_out;    }    dbg_out("sock remains:%d\n",soc_remains);    while(soc_remains>0) {      disable_pipe_signal(&saved_act);      write_len=send(con->soc,wp,soc_remains,0);      enable_pipe_signal(&saved_act);      if (write_len<0) {	if (errno==EINTR)	  continue;	err_out("Can not send %s %d\n",strerror(errno),errno);	goto close_out;      }      dbg_out("write len :%d\n",write_len);      wp += write_len;      total_write += write_len;      soc_remains -= write_len;    }    dbg_out("transfer %s %d/%d(%d)\n",path,total_write,size,file_remains);  }  rc=0; close_out:  close(fd);  if (rc<0)    dbg_out("Can not send file:%s %s %d\n",path,strerror(errno),errno);  return rc;}static intcreate_response(unsigned long type,const char *name,const size_t size,const char *dir,char **response){  int rc=0;  char *buff=NULL;  size_t act_len;  gchar *res;  size_t local_size;  int msg_fid;  char *local_name_p;  dbg_out("here:\n");  if ( ( (!name) && (type != IPMSG_FILE_RETPARENT) ) || (!dir) || (!response) )    return -EINVAL;  if (type != IPMSG_FILE_RETPARENT)    dbg_out("file:%s size:%d(%x)\n",	  name,size,size);  else    dbg_out("Return to parent.\n");  switch(type)    {    case IPMSG_FILE_REGULAR:      msg_fid=1;      local_size=size;      local_name_p=(char *)name;      break;    case IPMSG_FILE_DIR:      msg_fid=2;      local_size=0;      local_name_p=(char *)name;      break;    case IPMSG_FILE_RETPARENT:      msg_fid=3;      local_size=0;      local_name_p=".";      break;    default:      dbg_out("Invalid type:%d\n",type);      return -EINVAL;      break;  }  /*   *メッセージ形成   */  buff=g_malloc(IPMSG_BUFSIZ);  if (!buff)    return -ENOMEM;  snprintf(buff,IPMSG_BUFSIZ-1,"xxxx:%s:%x:%d:",	   local_name_p,local_size,msg_fid); /* 仮の長さを算出  */  buff[IPMSG_BUFSIZ-1]='\0';  act_len=strlen(buff);  snprintf(buff,IPMSG_BUFSIZ-1,"%04x:%s:%x:%d:",	   act_len,local_name_p,local_size,msg_fid); /* メッセージ作成  */  buff[IPMSG_BUFSIZ-1]='\0';  rc=-ENOSPC;  if (act_len != strlen(buff)) {    err_out("Message too long:%s\n",buff);    goto error_out;  }  rc=convert_string_ipmsg_proto(buff,(const gchar **)&res);  if (rc<0) {    err_out("Can not convert code set:%s\n",buff);    rc=-EINVAL;    goto error_out;  }  *response=res;  rc=0; error_out:  if (buff)    g_free(buff);  return rc;}static intsend_header(tcp_con_t *con,const char *response){  int rc;  size_t soc_remains;  ssize_t send_len;  char *wp;  int buff_len;  struct sigaction saved_act;  if ( (!con) || (!response) )    return -EINVAL;  soc_remains=strlen(response);  if (wait_socket(con->soc,WAIT_FOR_WRITE,TCP_SELECT_SEC)<0) {    err_out("Can not send socket\n");    goto error_out;  }  wp=(char *)response;  dbg_out("Send:%s(%d, %x)\n",wp,soc_remains,soc_remains);  while(soc_remains>0) {    disable_pipe_signal(&saved_act);    send_len=send(con->soc,wp,soc_remains,0);    enable_pipe_signal(&saved_act);    if (send_len<0) {      if (errno == EINTR)	continue;      rc=-errno;      err_out("Error:%s (%d)\n",strerror(errno),errno);      goto error_out;    }    wp += send_len;    soc_remains -= send_len;    dbg_out("soc remains:%d\n",soc_remains);  }  rc=0; error_out:  return rc; }static intread_directory_files(tcp_con_t *con,const char *parent,GnomeVFSFileInfo *info) {  int rc;  char *rel_path;  char *full_path;  char *res_message;  if ( (!con) || (!parent) || (!info) )    return -EINVAL;  if ( (!strcmp("..",info->name)) || (!strcmp(".",info->name) ) )    return -EINVAL;  if (info->type==GNOME_VFS_FILE_TYPE_REGULAR) {    rc=create_response(IPMSG_FILE_REGULAR,info->name,info->size,parent,&res_message);    if (rc<0)      return rc;    dbg_out("Send file:%s\n",res_message);    rc=send_header(con,res_message);    g_free(res_message);    if (rc<0)      return rc;  }  rc=-ENOMEM;  full_path=g_build_filename(parent,info->name,NULL);  if (!full_path)     return rc;  /* send file */  tcp_transfer_file(con,full_path,info->size,0);  g_free(full_path);  return 0;}static intsend_directory(tcp_con_t *con,const char *top_dir,const char *basename,GnomeVFSFileInfo *info){  int rc;  char *uri;  GnomeVFSResult res;  GnomeVFSDirectoryHandle *handle;  char *next_dir;  char *res_message;  if ( (!top_dir) || (!info) || (!basename) )    return -EINVAL;  rc=create_response(IPMSG_FILE_DIR,info->name,info->size,top_dir,&res_message);    if (rc<0)    return rc;  dbg_out("Send dir:%s (%s)\n",res_message,top_dir);  rc=send_header(con,res_message);  g_free(res_message);  if (rc<0)    return rc;        uri=gnome_vfs_get_uri_from_local_path(top_dir);  if (!uri)    return -ENOMEM;  /*   *ファイルを送付   */  res=gnome_vfs_directory_open(&handle,uri,GNOME_VFS_FILE_INFO_FOLLOW_LINKS);  res=gnome_vfs_directory_read_next(handle,info);  while (res==GNOME_VFS_OK) {    read_directory_files(con,top_dir,info);    res=gnome_vfs_directory_read_next(handle,info);  }  gnome_vfs_directory_close(handle);   /*   *ディレクトリを送付   */  res=gnome_vfs_directory_open(&handle,uri,GNOME_VFS_FILE_INFO_FOLLOW_LINKS);  if (res!=GNOME_VFS_OK) {    err_out("Can not open dir:%s %s (%d)\n",	    top_dir,	    gnome_vfs_result_to_string(res),	    res);    goto error_out;  }  res=gnome_vfs_directory_read_next(handle,info);  if (res!=GNOME_VFS_OK) {    if (res != GNOME_VFS_ERROR_EOF)      err_out("Can not read next dir:%s %s (%d)\n",	      top_dir,	      gnome_vfs_result_to_string(res),	      res);    goto error_out;  }  while (res==GNOME_VFS_OK) {    if ( (info->type==GNOME_VFS_FILE_TYPE_DIRECTORY) &&	 ( (strcmp(info->name,"..")) && (strcmp(info->name,"."))) ){      dbg_out("dir:%s\n",info->name);      next_dir=g_build_filename(top_dir,info->name,NULL);      if (!next_dir)	goto error_out;      rc=send_directory(con,next_dir,info->name,info);      g_free(next_dir);      if (rc<0)

⌨️ 快捷键说明

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