• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - 如何在 RPGLE 中构建 APNS 通知?

[复制链接]
菜鸟教程小白 发表于 2022-12-13 06:13:34 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

下午好,

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

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

您可以在下面看到我使用 Scott Klement 的套接字编程教程帮助我完成的程序。

可能与所有这些相关的代码在注释中标记为“APNS 通知格式开始”、“初始化”和“向 APNS 发送消息”,尽管我包含了整个程序以供引用。

我已阅读 Apple 网站 Provider Requirements 上的提供商要求但我仍然无法让一切正常工作。

我的程序编译,当我调试它/运行我通过建立实际连接的步骤时,我“认为”这部分没问题。

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

还有很多我不确定的事情

1) 我已获得作为 Base64 字符串的设备 token 。该字符串长度为 40 个奇数字符,但据我了解,Apple 声明设备 token 长度应为 32 个字节。在 RPGLE 中,1 个字符不是代表 1 个字节吗?如果是这种情况,那么我不能只将我的变量 token 声明为

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



Best Answer-推荐答案


这还不够接近,您使用的是字符而不是二进制数据。

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 流量。您可能会在以下方面得到更好的回应:

关于ios - 如何在 RPGLE 中构建 APNS 通知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29401333/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap