mail.c
上传用户:qys8201
上传日期:2021-12-11
资源大小:978k
文件大小:17k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #define _MAIL_C_
  2. #include "main.h"
  3. #include "mail.h"
  4. #include "util.h"
  5. #include "saacproto_serv.h"
  6. #include <malloc.h>
  7. #include <stdio.h>
  8. #include <time.h>
  9. #include <sys/types.h>
  10. #include <dirent.h>
  11. #include <sys/stat.h>
  12. typedef enum
  13. {
  14.     MS_NOUSE = 0,
  15.     MS_NEWMESSAGE,
  16.     MS_WAIT_ACK,
  17. } MAILSTATE;
  18. #define TEXT_MAX 1024
  19. struct mail
  20. {
  21.     int use;
  22.     unsigned int id_charname_hash;
  23.     char id_to[USERID_MAX];
  24.     char charname_to[CHARNAME_MAX];
  25.     char id_from[USERID_MAX];
  26.     char charname_from[CHARNAME_MAX];
  27.     char text[TEXT_MAX];
  28.     int option;
  29.     unsigned int message_id;
  30.     MAILSTATE state;
  31.     time_t recv_time;
  32. };
  33. struct mail *mailbuf;
  34. int mailbufsize = 0;
  35. static unsigned int
  36. getNextMessageID(void)
  37. {
  38.     FILE *fp;
  39.     unsigned int i;
  40.     char filename[1024];
  41.     char line[1000];
  42.     snprintf( filename, sizeof( filename ),
  43.               "%s/mail_id" , maildir );
  44.     fp = fopen( filename, "r" );
  45.     if( fp == NULL ){
  46.         fp = fopen( filename ,"w" );
  47.         if( fp == NULL ){
  48.             log( "不能创建 %s ... 使用同样的邮件ID,"
  49.                  " saac 发送变得缓慢!(id:9999)n", filename );
  50.             return 9999;
  51.         }
  52.         fprintf( fp, "10000n" );
  53.         fclose(fp);
  54.         return 1000;
  55.     }
  56.     fgets( line, sizeof(line), fp);
  57.     i = strtoul( line, NULL, 10 );
  58.     fclose(fp);
  59.     fp = fopen( filename, "w" );
  60.     if( fp == NULL ){
  61.         log( "不能写入新的ID到 %s ... 使用同样的数字!n", filename );
  62.         return i;
  63.     }
  64.     fprintf( fp, "%u", i+1 );
  65.     fclose(fp);
  66.     log( "新邮件ID:%un", i);
  67.     return i;
  68. }
  69. static int reallocMailBuf( void )
  70. {
  71.     struct mail *previous = mailbuf;
  72.     struct mail *newbuf;
  73.     int new_mailbufsize;
  74.     if( mailbufsize == 0 ){
  75.         new_mailbufsize = 1;
  76.     } else {
  77.         new_mailbufsize = mailbufsize * 2;
  78.     }
  79.     newbuf = ( struct mail * )calloc( 1, new_mailbufsize *
  80.                                       sizeof( struct mail ));
  81.     if( newbuf == NULL ){
  82.         log( "回复邮件缓冲: 内件不足!! 新邮件大小:%dn",
  83.              new_mailbufsize );
  84.         return -1;
  85.     }
  86.     memset( newbuf, 0 , new_mailbufsize * sizeof( struct mail ));
  87.     if( previous ) memcpy( (char*)newbuf, (char*)previous,
  88.                            mailbufsize * sizeof( struct mail ));
  89.     free( previous );
  90.     mailbufsize = new_mailbufsize;
  91.     mailbuf = newbuf;
  92.     log( "重新分配邮件缓冲: "
  93.          "新邮件缓冲:%d 旧地址:%x 新地址:%xn",
  94.          new_mailbufsize, (unsigned int)previous,(unsigned int)newbuf );
  95.     return 0;
  96. }
  97. static int mailbuf_finder = 0;
  98. static int allocMail( int use_msgid, unsigned int msgid  )
  99. {
  100.     int i;
  101.     for(i=0;i<mailbufsize;i++){
  102.         mailbuf_finder ++;
  103.         if( mailbuf_finder == mailbufsize ) mailbuf_finder = 0;
  104.         if( mailbuf[mailbuf_finder].use == 0 ){
  105.             mailbuf[mailbuf_finder].use = 1;
  106.             mailbuf[mailbuf_finder].text[0] = 0;
  107.             mailbuf[mailbuf_finder].id_to[0] = 0;
  108.             mailbuf[mailbuf_finder].charname_to[0] = 0;
  109.             mailbuf[mailbuf_finder].id_from[0] = 0;
  110.             mailbuf[mailbuf_finder].charname_from[0] = 0;
  111.             if( use_msgid ){
  112.                 mailbuf[mailbuf_finder].message_id = msgid;
  113.             } else {
  114.                 mailbuf[mailbuf_finder].message_id = getNextMessageID();
  115.             }
  116.             mailbuf[mailbuf_finder].state = MS_NEWMESSAGE;
  117.             mailbuf[mailbuf_finder].recv_time = time(NULL);
  118.             return mailbuf_finder;
  119.         }
  120.     }
  121.     log( "分配邮件: 邮件缓冲失败.正在进行分配...n" );
  122.     if( reallocMailBuf() < 0 ){
  123.         log( "分配邮件: 分配失败n" );
  124.     } else {
  125.         return allocMail(use_msgid, msgid );
  126.     }
  127.     return -1;
  128. }
  129. void receiveMail( char *id_from,
  130.              char *charname_from,
  131.              char *id_to,
  132.              char *charname_to,
  133.              char *message,
  134.              int option,
  135.              int use_msgid,
  136.              unsigned int msgid 
  137.              )
  138. {
  139.     char id_charname[1024];
  140.     int h, mbindex;
  141.     snprintf( id_charname, sizeof( id_charname), "%s_%s", id_to, charname_to );
  142.     h = hashpjw( id_charname ) & 0xff ;
  143.     if( (mbindex = allocMail(use_msgid, msgid )) < 0 ){
  144.         log( "回复邮件: 获取新的邮件缓冲失败.n" );
  145.         return;
  146.     }
  147.     mailbuf[mbindex].id_charname_hash = h;
  148.     snprintf( mailbuf[mbindex].text, sizeof( mailbuf[mbindex].text ), "%s", message );
  149.     snprintf( mailbuf[mbindex].id_to, sizeof( mailbuf[mbindex].id_to ), "%s", id_to );
  150.     snprintf( mailbuf[mbindex].charname_to, sizeof( mailbuf[mbindex].charname_to ), "%s", charname_to );
  151.     snprintf( mailbuf[mbindex].id_from, sizeof( mailbuf[mbindex].id_from ),"%s", id_from );
  152.     snprintf( mailbuf[mbindex].charname_from, sizeof( mailbuf[mbindex].charname_from ),"%s", charname_from );
  153.     mailbuf[mbindex].option = option;
  154.     {
  155.         char childname[1000];
  156.         char savefile[1000];
  157.         char charname2[CHARNAME_MAX*2+1];
  158.         char text2[TEXT_MAX*2+1];
  159.         FILE *fp;
  160.         
  161.         snprintf( childname, sizeof( childname ),"%u" ,
  162.                   mailbuf[mbindex].message_id );
  163.         makeDirFilename( savefile , sizeof(savefile), maildir, h, childname );
  164.         fp = fopen( savefile, "w" );
  165.         if( fp == NULL ){
  166.             log( "回复邮件 : 不能保存邮件文件: %s %sn",
  167.                  savefile, strerror( errno ));
  168.             return;
  169.         }
  170. #define TO_ID_HEAD "ToID: "
  171. #define TO_CHAR_HEAD "ToChar: "
  172. #define FROM_ID_HEAD "FromID: "
  173. #define FROM_CHAR_HEAD "FromChar: "
  174. #define OPTION_HEAD "Option: "
  175. #define TEXT_HEAD "Text: "
  176.         
  177.         fprintf( fp, TO_ID_HEAD "%sn", id_to );
  178.         snprintf( charname2, sizeof( charname2), "%s", charname_to );
  179.         fprintf( fp, TO_CHAR_HEAD "%sn", makeEscapeString( charname_to,
  180.                                                charname2,sizeof(charname2)) );
  181.         fprintf( fp, FROM_ID_HEAD "%sn", id_from );
  182.         snprintf( charname2, sizeof( charname2), "%s", charname_from );
  183.         fprintf( fp, FROM_CHAR_HEAD "%sn", makeEscapeString( charname_from,
  184.                                                charname2,sizeof(charname2)) );
  185.         fprintf( fp, OPTION_HEAD "%dn", option );
  186.         snprintf( text2, sizeof( text2 ) , "%s", message );
  187.         fprintf( fp, TEXT_HEAD "%sn", makeEscapeString( message,
  188.                                                text2, sizeof(text2)) );
  189.         fclose(fp);
  190. {
  191. static int mailnum=0;
  192. if( mailnum%10 == 0)
  193. log(".");
  194. mailnum = (++mailnum%1000);
  195. if( mailnum == 0 )
  196. log("n");
  197. }
  198.     }
  199.     {
  200.         extern gmsv gs[MAXCONNECTION];
  201.         int i;
  202.         for(i=0;i<MAXCONNECTION;i++){
  203.             if( gs[i].use && gs[i].name[0] ){
  204.                 saacproto_Message_send( i,
  205.                                         id_from, charname_from,
  206.                                         id_to, charname_to,
  207.                                         message, option,
  208.                                         mailbuf[mbindex].message_id );
  209.                 mailbuf[mbindex].state = MS_WAIT_ACK;
  210.             }
  211.         }
  212.     }
  213. }
  214. void receiveMailAck( char *id, char *charname, int a , int mesgid )
  215. {
  216.     int i;
  217.     unsigned int h;
  218.     char id_charname[1024];
  219.     snprintf( id_charname, sizeof( id_charname), "%s_%s", id, charname );    
  220.     h = hashpjw( id_charname ) & 0xff ;
  221.     for(i=0;i<mailbufsize;i++){
  222.         if( mailbuf[i].message_id == mesgid ){
  223.             if( mailbuf[i].use
  224.                 && mailbuf[i].id_charname_hash == h
  225.                 && strcmp( mailbuf[i].id_to, id ) == 0
  226.                 && strcmp( mailbuf[i].charname_to, charname ) == 0
  227.                 && mailbuf[i].state == MS_WAIT_ACK ){
  228.                 char savefile[1024];
  229.                 char childname[1000];
  230.                 snprintf( childname,sizeof(childname),"%u",
  231.                           mailbuf[i].message_id );
  232.                 makeDirFilename( savefile, sizeof(savefile),maildir,
  233.                                  h, childname );
  234.                 if( unlink( savefile ) != 0 ){
  235.                     log( "failed to unlink %s: %sn",
  236.                          savefile, strerror(errno ));
  237.                 } else {
  238.                     log( "回复邮件: 删除邮件 "
  239.                          "%u 从 %s(%s) to %s(%s)n",
  240.                          mailbuf[i].message_id,
  241.                          mailbuf[i].id_from,
  242.                          mailbuf[i].charname_from,
  243.                          mailbuf[i].id_to,
  244.                          mailbuf[i].charname_to );
  245.                 }
  246.                 memset( &mailbuf[i], 0 , sizeof( mailbuf[0] ));
  247.                 return;
  248.             } else {
  249.                 log( "回复邮件: 无用信息或ID或名称或声明严重错误" );
  250.                 log( "use[%d] h[%d][%d] id[%s][%s] nm[%s][%s] st[%d]n",
  251.                      mailbuf[i].use, mailbuf[i].id_charname_hash, h,
  252.                      mailbuf[i].id_to, id,
  253.                      mailbuf[i].charname_to, charname,
  254.                      mailbuf[i].state);
  255.             }
  256.         }
  257.     }
  258.     log( "回复邮件: 邮件 %u 不能从 %s(%s) 找到n",
  259.          mesgid, id,charname );
  260. }
  261. void flushMail( int fd,
  262.            char *id,
  263.            char *charname )
  264. {
  265.     int i,c=0;
  266.     unsigned int h ;
  267.     char id_charname[1000];
  268. #define MAX_FLUSH_MAIL 1024
  269.     int flush_index[MAX_FLUSH_MAIL];
  270.     int flush_i=0;
  271.     snprintf( id_charname, sizeof( id_charname ) , "%s_%s", id, charname );
  272.     h = hashpjw( id_charname );
  273.     // Nuke +1
  274.     log("邮件缓冲大小:%d (%s)n",mailbufsize,chartime());
  275.     // Nuke *1
  276.     for(i=0;(i<mailbufsize)&&(i<MAX_FLUSH_MAIL);i++){
  277.         if( mailbuf[i].id_charname_hash == h &&
  278.             mailbuf[i].use &&
  279.             strcmp( mailbuf[i].id_to , id ) == 0 &&
  280.             strcmp( mailbuf[i].charname_to, charname ) == 0 ){
  281.             log( "消息ID:%un", mailbuf[i].message_id );
  282.             flush_index[flush_i++] = i;
  283.             c++;
  284.         }
  285.     }
  286.     for(i=0; i< flush_i ; i++ ){
  287.         int j;
  288.         for(j=0; j < flush_i-1 ; j++ ){
  289.             if( mailbuf[flush_index[j]].message_id >
  290.                 mailbuf[flush_index[j+1]].message_id ){
  291.                 int sw = flush_index[j];
  292.                 flush_index[j] = flush_index[j+1];
  293.                 flush_index[j+1] = sw;
  294.                 log( "inverted %d and %d in %d n", flush_index[j],
  295.                      flush_index[j+1], j );
  296.             }
  297.         }
  298.     }
  299.     /*   端卞霜耨允月 */
  300.     for(i=0;i< flush_i; i++ ){
  301.         /* flush 及桦宁反}flush毛霜耨仄化五凶必□丞扔□田□卞
  302.            覆仄化分仃霜耨允木壬中中 */
  303.         saacproto_Message_send( fd,
  304.                                 mailbuf[flush_index[i]].id_from,
  305.                                 mailbuf[flush_index[i]].charname_from,
  306.                                 mailbuf[flush_index[i]].id_to,
  307.                                 mailbuf[flush_index[i]].charname_to,
  308.                                 mailbuf[flush_index[i]].text,
  309.                                 mailbuf[flush_index[i]].option,
  310.                                 mailbuf[flush_index[i]].message_id );
  311.         mailbuf[flush_index[i]].state = MS_WAIT_ACK;
  312.         log( "分类邮件ID:%un",
  313.                 mailbuf[flush_index[i]].message_id );
  314.     }
  315.     // Nuke *1
  316.     log( "邮件: 发送 %d 封邮件到 %s(%s)(%s)n", c, id, charname ,chartime());
  317. }
  318. // Nuke start: To expire undelivered mail
  319. #define MAIL_EXPIRE_TIME 3600
  320. void
  321. expireMail()
  322. {
  323.     int i,c=0;
  324.     unsigned int h ;
  325.     char id_charname[1000];
  326.     time_t now=time(NULL);
  327.     
  328.     /* 1荚及flush 匹霜耨允月    醒 */
  329. #define MAX_FLUSH_MAIL 1024
  330.     int flush_index[MAX_FLUSH_MAIL];
  331.     int flush_i=0;
  332.     // Nuke +1
  333.     log("邮件缓冲大小:%d (%s)n",mailbufsize,chartime());
  334.     // Nuke *1
  335.     for(i=0;(i<mailbufsize)&&(i<MAX_FLUSH_MAIL);i++){
  336.         if(mailbuf[i].use && (now - mailbuf[i].recv_time >= MAIL_EXPIRE_TIME)) {
  337.             log( "消息ID:%u 已过期n", mailbuf[i].message_id );
  338.             flush_index[flush_i++] = i;
  339.             c++;
  340.         }
  341.     }
  342.     /*   端卞霜耨允月 */
  343.     for(i=0;i< flush_i; i++ ){
  344.         
  345.         snprintf( id_charname, sizeof( id_charname), "%s_%s", 
  346.          mailbuf[flush_index[i]].id_to, 
  347.          mailbuf[flush_index[i]].charname_to );
  348.         h = hashpjw( id_charname ) & 0xff ;
  349. {
  350.             char savefile[1024];
  351.             char childname[1000];
  352.             snprintf( childname,sizeof(childname),"%u",
  353.              mailbuf[flush_index[i]].message_id );
  354.             makeDirFilename( savefile, sizeof(savefile),maildir,
  355.              h, childname );
  356.             if( unlink( savefile ) != 0 ){
  357.                 log( "failed to unlink %s: %sn",
  358.                 savefile, strerror(errno ));
  359.             } else {
  360.                 log( "过期邮件: 删除游戏 "
  361.                  "%u 从 %s(%s) 到 %s(%s)n",
  362.                         mailbuf[flush_index[i]].message_id,
  363.                         mailbuf[flush_index[i]].id_from,
  364.                         mailbuf[flush_index[i]].charname_from,
  365.                         mailbuf[flush_index[i]].id_to,
  366.                         mailbuf[flush_index[i]].charname_to );
  367.             }
  368.             memset( &mailbuf[flush_index[i]], 0 , sizeof( mailbuf[0] ));
  369. }
  370.     }
  371.     // Nuke *1
  372.     log( "过期邮件: 过期 %d 消息 (%s)n", c ,chartime());
  373. }
  374. int readMail( char *dir )
  375. {
  376.     int i, read_count=0;
  377.     for( i=0; i<256; i++){
  378.         char dirname[1000];
  379.         DIR *d;
  380.         snprintf(dirname, sizeof( dirname ), "%s/0x%x", dir, i );
  381.         d = opendir(dirname);
  382.         if(d == NULL ){
  383. mkdir( dirname, 0755);
  384. log("创建 %sn", dirname);
  385.             continue;
  386.         }
  387.         while(1){
  388.             struct dirent *de;        
  389.             de = readdir( d );
  390.             if( de == NULL )break;
  391.             if( de->d_name[0] != '.' ){
  392.                 char filename[1000];
  393.                 FILE *fp;
  394.                 struct stat s;
  395.                 snprintf( filename, sizeof( filename),
  396.                           "%s/%s", dirname, de->d_name );
  397.                 if( stat( filename, &s ) < 0 ){
  398.                     continue;
  399.                 }
  400.                 if( !(s.st_mode & S_IFREG)) continue;
  401.                 fp = fopen( filename, "r" );
  402.                 if( fp == NULL ){
  403.                     log( "不能打开文件 %s %sn",filename,strerror(errno));
  404.                     continue;
  405.                 }
  406.                 {
  407.                     char line[16384];
  408.                     char toid[1000] , fromid[1000];
  409.                     char tochar[CHARNAME_MAX*2+1];
  410.                     char fromchar[CHARNAME_MAX*2+1];
  411.                     char text[TEXT_MAX*2+1];
  412.                     int opt=0;
  413.                     toid[0] = fromid[0] = tochar[0] =
  414.                         fromchar[0] = text[0] = 0;
  415.                     fgets( line, sizeof(line), fp );                    
  416.                     chop(line);
  417.                     if( strncmp( TO_ID_HEAD , line, strlen(TO_ID_HEAD) )==0){
  418.                         snprintf( toid , sizeof( toid ),"%s",
  419.                                   line+strlen(TO_ID_HEAD ));
  420.                     }
  421.                     fgets( line, sizeof( line ), fp );
  422.                     chop(line);
  423.                     if( strncmp( TO_CHAR_HEAD, line,strlen(TO_CHAR_HEAD))==0){
  424.                         snprintf( tochar, sizeof( tochar ), "%s",
  425.                                   line+strlen( TO_CHAR_HEAD ));
  426.                         makeStringFromEscaped( tochar );
  427.                     }
  428.                     fgets( line, sizeof( line ),fp );
  429.                     chop(line);                    
  430.                     if( strncmp( FROM_ID_HEAD,line,strlen(FROM_ID_HEAD))==0){
  431.                         snprintf( fromid, sizeof( fromid ),"%s",
  432.                                   line + strlen( FROM_ID_HEAD ));
  433.                     }
  434.                     fgets( line,sizeof(line),fp);
  435.                     chop(line);                    
  436.                     if(strncmp(FROM_CHAR_HEAD,line,strlen(FROM_CHAR_HEAD))==0){
  437.                         snprintf( fromchar, sizeof( fromchar ),
  438.                                   line + strlen(FROM_CHAR_HEAD ));
  439.                         makeStringFromEscaped( fromchar );
  440.                     }
  441.                     fgets( line,sizeof(line),fp);
  442.                     chop(line);                    
  443.                     if( strncmp( OPTION_HEAD,line, strlen(OPTION_HEAD))==0){
  444.                         opt = atoi( line + strlen( OPTION_HEAD ) );
  445.                     }
  446. fgets( line, sizeof( line),fp);
  447.                     chop(line);                    
  448.                     if( strncmp(TEXT_HEAD,line,strlen(TEXT_HEAD))==0){
  449.                         snprintf( text, sizeof( text), "%s",
  450.                                   line + strlen( TEXT_HEAD ));
  451.                         makeStringFromEscaped( text );
  452.                     }
  453.                     if( toid[0] == 0 || fromid[0] == 0 ||
  454.                         tochar[0] == 0 || fromchar[0] == 0 ||
  455.                         text[0] == 0 ){
  456.                         log( "有问题邮件! %s 接收ID[%c] 接收名字[%c]"
  457.                              " 发送ID[%c] 发送名字[%c] 文本[%c]n",
  458.                              filename,
  459.                              toid[0], tochar[0], fromid[0], fromchar[0],
  460.                              text[0] );
  461.                         // Nuke +1 1027: Close for safe
  462.                         fclose(fp);
  463.                         continue;
  464.                     }
  465.                     receiveMail( fromid, fromchar,
  466.                                  toid, tochar,
  467.                                  text, opt , 1,
  468.                                  strtoul(de->d_name,NULL,10));
  469.                     read_count++;                    
  470.                 }
  471.                 fclose(fp);
  472.             }
  473.         }
  474.         closedir(d);
  475.     }
  476.     log( "读取邮件: 在'%s'目录里读取到 %d 封邮件 n", dir, read_count );
  477.     return 0;
  478. }