如何在RPGLE中构建APNS通知?

时间:2015-04-01 21:39:22

标签: ios sockets notifications apple-push-notifications rpgle

下午好,

我正在尝试创建一个套接字程序,它连接到Apple推送通知服务(APNS)并发送推送通知。

我想知道是否有人可以帮助我实际编写APNS通知。

下面你可以看到我使用Scott Klement的套接字编程教程来帮助我的程序。

可能与此相关的代码标记为' APNS通知格式开始'初始化'以及'向APNS制定消息'在评论中虽然我包括整个计划以供参考。

我已阅读Apple网站Provider Requirements上的提供商要求,但我仍然无法使所有内容正常运行。

我的程序编译,当我调试它/运行我已经过去建立一个实际连接的步骤,所以我认为'这部分还可以。

我希望在item3数据结构中的变量errid中从Apple获取错误标识符。 Apple在提供商要求中声明,如果出现错误,他们会返回状态代码,但该特定变量仍为1077952576

还有很多其他我不确定的事情

1)我已将设备令牌作为Base64字符串。字符串是40个奇怪的字符,但据我所知,Apple声明设备令牌长度应该是32个字节。在RPGLE中,1个字符代表1个字节吗?如果是这样,那么我就不能将我的变量标记声明为

D   token                       32a

因为它会被切断?

2)当我的变量errid中返回从Apple接收正确的错误标识符时,是否有人能够告诉我我做错了什么?

非常感谢任何帮助

H DFTACTGRP(*NO) BNDDIR('QC2LE')
D/copy socket_h
D/copy gskssl_h

*==============================================================*
*  APNS Notification Format Begin                               
*==============================================================*
D request         s           1000a   varying

D framehdr        ds                         
D   command                      3I 0 inz(2) 
D   framelen                    10I 0        

D framedta        s            500a   varying          

D item1           ds                                   
D   itemid1                      3I 0 inz(1)           
D   itemlen1                     5I 0 inz(%size(token))
D   token                       64a    

D item2           ds                                   
D   itemid2                      3I 0 inz(2)           
D   itemlen2                     5I 0                  
D   payload                    100a   varying          

D item3           ds                                   
D   itemid3                      3I 0 inz(3)           
D   itemlen3                     5I 0 inz(%size(errid))
D   errid                       10I 0

D item4           ds                                      
D   itemid4                      3I 0 inz(4)              
D   itemlen4                     5I 0 inz(%size(expire))  
D   expire                      10I 0 inz(0)              

D item5           ds                                      
D   itemid5                      3I 0 inz(5)              
D   itemlen5                     5I 0 inz(%size(priority))
D   priority                    10I 0 inz(10)    

*==============================================================*
*  APNS Notification Format End                                 
*==============================================================*         

D gsk_strerror    PR              *   extproc('gsk_strerror')
D  gsk_ret_value                10I 0 value                  

D CreateEnv       PR                  like(gsk_handle)       

D ConnSock        PR            10I 0                        
d   host                       256A   const                  
D   port                        10I 0 value                  

D UpgradeSock     PR                  like(gsk_handle)      
D    SslEnv                           like(gsk_handle) value
D    sock                       10I 0 value          

D CloseSsl        PR                                        
D    Handle                           like(gsk_handle) value

D CloseSslEnv     PR                                        
D    SslEnv                           like(gsk_handle) value

D ReportError     PR                                     

D EscapeMsg       PR          

D errMsg          s             80A   varying            
D CRLF            c                   x'0d25'            
D env             s                   like(gsk_handle)   
D s               s             10I 0                    
D connto          ds                  likeds(sockaddr_in)
D SslSock         s                   like(gsk_handle)    
D cmd             s            400A  
D len             s             10I 0
D bytesSent       s             10I 0
D Reply           s           1000A  
D bytesRead       s             10I 0
D left            s             10I 0
D buf             s               *  
D received        s             10I 0
D dataPos         s             10I 0
D wait            s              1A  
D rc              s             10I 0

/free                     

// Initialize
token = 'MyDevToken';
payload = '{"aps":{"alert":"You have mail"}}';         
itemlen1 = %len(payload);                              
framedta = item1 + item2 + item3 + item4 + item5;      
framelen = %len(framedta);                             

request = framehdr + framedta;                         

// Create SSL Environment

env = CreateEnv();       
If (env = *NULL);        
   EscapeMsg();          
Endif;               

// Connect a socket to an SSL server (using normal socket calls)
// NOTE: Sandbox is the development environment                 

s = ConnSock('gateway.sandbox.push.apple.com': 2195);        

// Upgrade the socket to SSL                                    

SSLSock = UpgradeSock(env: s);                                  
If (SSLSock = *NULL);   
   EscapeMsg();
Endif;                                                    

// **** Formulate message to APNS ******
len = %len(%trimr(request));

callp gsk_secure_soc_write(SSLSock
                          : %addr(request)
                          : len
                          : bytesSent); 



 // Close everything and end the program

 CloseSsl(SslSock);                  
 CloseSslEnv(Env);                   

 *inlr = *on;                           

 /end-free       


*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CreateEnv(): Create an SSL environment for client sockets 
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CreateEnv       B                                          
D CreateEnv       PI                  like(gsk_handle)       
D rc              s             10I 0                        
D SslEnv          s                   like(Gsk_handle)       

/free                                                        

// Create an SSL environment with default values:           

rc = gsk_environment_open(SslEnv);                         
If (rc <> GSK_OK);                                         
 errMsg = %str(gsk_strerror(rc));                        
 return *NULL;                                           
Endif;                                                     

// Instruct environment to use the *SYSTEM certificate store

rc = gsk_attribute_set_buffer( SslEnv                      
                           : GSK_OS400_APPLICATION_ID    
                           : 'SUMITOMO_APNS_PUSH'        
                           :0 ); 
If (rc<>GSK_OK);
   errMsg = %str(gsk_strerror(rc));
   gsk_environment_close( SslEnv );
   return *NULL;
Endif;

//Tell the environment that this is a client connection
rc = gsk_attribute_set_enum( SslEnv
     : GSK_SESSION_TYPE     
     : GSK_CLIENT_SESSION );

If (rc <> GSK_OK);                 
   errMsg = %str(gsk_strerror(rc));
   gsk_environment_close( SslEnv );
   return *NULL;                   
Endif;                             

// Activate the new environment     

rc = gsk_environment_init( SslEnv );
If (rc <> GSK_OK);                  
   errMsg = %str(gsk_strerror(rc)); 
   gsk_environment_close( SslEnv ); 
   return *NULL;                    
Endif;  

return SslEnv;

/end-free
P            E             

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* ConnSock(): Create a TCP Socket and connect to a host     
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P ConnSock        B                                          
D ConnSock        PI            10I 0                        
d   host                       256A   const                  
D   port                        10I 0 value                  
D s               s             10I 0                        
D addr            s             10U 0                        

/free                                                           

// look up host                           

addr = inet_addr(%trim(host));            
If (addr = INADDR_NONE);                  
   p_hostent = gethostbyname(%trim(host));
If (p_hostent = *NULL);                
   errMsg = 'Host not found!';         
   EscapeMsg();                        
Endif;                                 
   addr = h_addr;                         
Endif;

// Create a socket                           

s = socket(AF_INET: SOCK_STREAM: IPPROTO_IP);
If (s < 0);                              
   ReportError();                        
Endif;

// connect to the host                                

connto = *ALLx'00';                                
connto.sin_family = AF_INET;                       
connto.sin_addr   = addr;                          
connto.sin_port   = port;                          

If (connect(s: %addr(Connto): %size(connto)) = -1);
  callp close(S);                                 
  ReportError();                                  
Endif;                                             

return s;
/end-free
P             E

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* UpgradeSock():  Upgrade a socket to use SSL               
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P UpgradeSock     B                                          
D UpgradeSock     PI                  like(gsk_handle)       
D    SslEnv                           like(gsk_handle) value 
D    sock                       10I 0 value                  
D Handle          s                   like(Gsk_handle)       

/free     

rc = gsk_secure_soc_open(SslEnv: Handle);    
If (rc <> GSK_OK);                 
   errMsg = %str(gsk_strerror(rc));
   return *NULL;                   
Endif; 

rc = gsk_attribute_set_numeric_value(Handle
     : GSK_HANDSHAKE_TIMEOUT
     : 30 );

If (rc <> GSK_OK);                 
   errMsg = %str(gsk_strerror(rc));
   gsk_secure_soc_close(Handle);   
   return *NULL;    
Endif;

rc = gsk_secure_soc_init( Handle );
If (rc <> GSK_OK);                 
   errMsg = %str(gsk_strerror(rc));
   gsk_secure_soc_close(Handle);   
   return *NULL;                   
Endif;         

return Handle;
/end-free
P             E

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CloseSsl():  Close an SSL socket                          
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CloseSsl        B                                          
D CloseSsl        PI                                         
D    Handle                           like(gsk_handle) value 
/free                                                       
   gsk_secure_Soc_close( handle);                        
/end-free                                                   
P                 E    

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CloseSslEnv():  Close SSL Environment                     
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CloseSslEnv     B                                          
D CloseSslEnv     PI                                         
D    SslEnv                           like(gsk_handle) value 
/free                                                       
   gsk_environment_close( SslEnv );                      
/end-free
P     E         

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* EscapeMsg(): Send an escape message w/reason for SSL failure      
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P EscapeMsg       B                                                  
D EscapeMsg       PI                                                 
D SndPgmMsg       PR                  ExtPgm('QMHSNDPM')             
D   MessageID                    7A   Const                          
D   QualMsgF                    20A   Const                          
D   MsgData                    256A   Const                          
D   MsgDtaLen                   10I 0 Const                          
D   MsgType                     10A   Const                          
D   CallStkEnt                  10A   Const                          
D   CallStkCnt                  10I 0 Const                          
D   MessageKey                   4A                                  
D   ErrorCode                    1A        

D ErrorCode       DS                        
D  BytesProv                    10I 0 inz(0)
D  BytesAvail                   10I 0 inz(0)  

D wwTheKey        S              4A 

/free
SndPgmMsg( 'CPF9897'
: 'QCPFMSG   *LIBL'   
: errMsg              
: %len(%trimr(errMsg))
: '*ESCAPE'           
: '*CTLBDY'           
: 1                   
: wwTheKey            
: ErrorCode );
/end-free
P          E

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* ReportError():  Send an escape message explaining any errors    
*                 that occurred.                                  
*                                                                 
*  This function requires binding directory QC2LE in order        
*  to access the __errno() function.                              
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P ReportError     B                                                
D ReportError     PI                                               

D get_errno       PR              *   ExtProc('__errno')           
D ptrToErrno      s               *                                
D errno           s             10I 0 based(ptrToErrno)      

D QMHSNDPM        PR                  ExtPgm('QMHSNDPM')
D   MessageID                    7A   Const             
D   QualMsgF                    20A   Const             
D   MsgData                      1A   Const             
D   MsgDtaLen                   10I 0 Const             
D   MsgType                     10A   Const             
D   CallStkEnt                  10A   Const             
D   CallStkCnt                  10I 0 Const             
D   MessageKey                   4A                     
D   ErrorCode                 8192A   options(*varsize)

D ErrorCode       DS                  qualified
D  BytesProv              1      4I 0 inz(0)   
D  BytesAvail             5      8I 0 inz(0)   

D MsgKey          S              4A
D MsgID           s              7A

/free 

ptrToErrno = get_errno();    
MsgID = 'CPE' + %char(errno);

QMHSNDPM( MsgID
 : 'QCPFMSG   *LIBL'
 : ' '              
 : 0                
 : '*ESCAPE'        
 : '*PGMBDY'        
 : 1     
 : MsgKey              
 : ErrorCode         );           
 /end-free
 P          E

1 个答案:

答案 0 :(得分:1)

这甚至不接近,你使用的是字符而不是二进制数据。

cmd = '2' + 3 + 1 + 64 + 'x' + 2 + 50 + '{"aps":{"alert":"You have mail"}} +
      3 + 3 + '001'

这应该更接近;但它完全脱离了我的头脑,完全没有经过考验......

 d request         s           1000a   varying

 d frame_hdr       ds
 d  cmd                           1a   inz(x'02')
 d  frame_len                    10i 0

 d frame_data      s            500a   varying

 d device_item     ds 
 d                                1a   inz(x'01')
 d                                5i 0 inz(%size(device_item))
 d  token                        32a 

 d item_hdr        ds
 d  id                            1a   inz(x'02')
 d  item_len                      5i 0


 d item_data       s            100a   varying

   item_data = '{"aps":{"alert":"You have mail"}}';
   item_len = %len(item_data);

   token = myDevID;
   frame_data = device_item + item_hdr + item_data;
   frame_len = %len(frame_data);

   request = frame_hdr + frame_data;

   callp gsk_secure_soc_write(SSLSock
                      : %addr(request:*DATA)
                      : %len(request)
                      : bytesSent); 

我之前没有在IBM i上完成原始套接字,您可能需要将EBCDIC转换为ASCII。我不认为你需要担心小端与大端。

RPG可能不是最好的选择,鉴于Java PNS

等项目的存在,Java可能是更好的选择

Stackoverflow没有大量的RPG / IBM i流量。您可以对以下内容做出更好的回应: