× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



You'd need to decode the base64 string into it's 32 byte binary value.

But kevin is correct, you're writing to the socket...but never reading from
it in the code you've posted.

Per the docs you posted a link to on SO
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html

The item ID is a 1-byte value. The device token is a 32 byte binary value.

In RPGLE, 3i 0 is a two byte integer. RPGLE doesn't support a one-byte
integer, You'll have to use a character field with a hexidecimal value

D item1 ds
D itemid1 1a inz(x'01')
D itemlen1 5I 0 inz(%size(token))
D token 32a

I have no experience with APNS, so I'm far from the best resource...

But have you looked at this document also?
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html

To you have the certs installed you need to talk via APNS?

In the same vein..I don't think you can just post a APN..I think you have
to have an iOS app you're talking to.
The link Buck posted on another of your SO posts in a nice tutorial of how
to create a simple app that receives the push notifications...
http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1


Good luck!
Charles



On Thu, Apr 2, 2015 at 3:52 PM, Kevin Bucknum <Kevin@xxxxxxxxxxxxxxxxxxx>
wrote:

1 - a 32 byte token would be about 40 bytes base64 encoded. I think if
you decode what they send, it would be 32 characters.
2 - I don't see anywhere in the code where you read a response back from
them.

-----Original Message-----
From: RPG400-L [mailto:rpg400-l-bounces@xxxxxxxxxxxx] On Behalf Of
RWesh@xxxxxxxxxxx
Sent: Thursday, April 02, 2015 2:23 PM
To: rpg400-l@xxxxxxxxxxxx
Subject: Can anyone help me with an RPGLE Socket implementation for
APNS?(Formulating the notification)

I am attempting to create a socket program which connects to Apple Push
Notification Service (APNS) and sends a push notification.
I am wondering if anyone can help me with the actual writing of the APNS
notification.
Below you can see my program which I used Scott Klement's Socket
Programming tutorial to help me with.
The code that is probably relevant to all of this is marked as 'APNS
Notification Format Begin', 'Initialize', and 'Formulate message to
APNS'
in comments although I included the entire program for reference.
I have read the Provider Requirements on Apple's site Provider
Requirements but I am still having trouble getting everything working.
My program compiles and when I debug it / run through the steps I get
past establishing an actual connection so I 'think' that this part is
OK.
What I am hoping is to get back an error identifier from Apple in the
variable errid within the item3 data structure. Apple states in the
Provider Requirements that they return a status code if there is an
error but that particular variable remains at 1077952576 There are also
quite a few other things that I am unsure of
1) I have been given the device token as a Base64 string. The string is
40 some odd characters long but from what I understand, Apple states
device token length should be 32 bytes. In RPGLE doesn't 1 character
represent 1 byte? If that's the case then I couldn't just declare my
variable token as
D token 32a
because it would get cut off?
2) Is anyone able to tell me what I am doing wrong when it comes back to
receiving a proper error identifier from Apple in my variable errid?
Any help would be greatly appreciated

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


Russell Wesh, PMP | Data Integration Specialist Sumitomo Drive
Technologies Sumitomo Machinery Corp. of America
Tel: +1-757-485-3355 ext. 8633
Cell: +1-757-822-4446
Fax: +1-757-485-7190
www.sumitomodrive.com | How are we doing?



This document should only be read by those persons to whom it is
addressed and is not intended to be relied upon by any person without
subsequent written confirmation of its contents. Accordingly, Sumitomo
Machinery Corporation disclaims all responsibility and accept no
liability (including in negligence) for the consequences for any person
acting, or refraining from acting, on such information prior to the
receipt by those persons of subsequent written confirmation. If you
have received this e-mail message in error, please notify us immediately
by telephone. Please also destroy and delete the message from your
computer. Any form of reproduction, dissemination, copying, disclosure,
modification, distribution and/or publication of this e-mail message is
strictly prohibited.
--
This is the RPG programming on the IBM i (AS/400 and iSeries) (RPG400-L)
mailing list
To post a message email: RPG400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/rpg400-l
or email: RPG400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at http://archive.midrange.com/rpg400-l.




Kevin Bucknum
Senior Programmer Analyst
MEDDATA/MEDTRON
Tel: 985-893-2550

--
This is the RPG programming on the IBM i (AS/400 and iSeries) (RPG400-L)
mailing list
To post a message email: RPG400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/rpg400-l
or email: RPG400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at http://archive.midrange.com/rpg400-l.



As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:
Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.