4 # Copyright (c) 2007, Cameron Rich
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
11 # * Redistributions of source code must retain the above copyright notice,
12 # this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # * Neither the name of the axTLS project nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26 # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28 # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #===============================================================
34 # Transforms function signature into SWIG format
35 sub transformSignature
39 $line =~ s/STDCALL //g;
40 $line =~ s/EXP_FUNC/extern/g;
42 # make API Java more 'byte' friendly
43 $line =~ s/uint32_t/int/g;
44 $line =~ s/const uint8_t \* /const unsigned char \* /g;
45 $line =~ s/\(void\)/()/g;
46 if ($ARGV[0] eq "-java")
48 $line =~ s/.*ssl_read.*//g;
49 $line =~ s/const uint8_t \*(\w+)/const signed char $1\[\]/g;
50 $line =~ s/uint8_t/signed char/g;
52 elsif ($ARGV[0] eq "-perl")
54 $line =~ s/const uint8_t \*(\w+)/const unsigned char $1\[\]/g;
55 $line =~ s/uint8_t/unsigned char/g;
59 $line =~ s/const uint8_t \*session_id/const unsigned char session_id\[\]/g;
60 $line =~ s/const uint8_t \*\w+/unsigned char *INPUT/g;
61 $line =~ s/uint8_t/unsigned char/g;
73 next if $line =~ /ssl_x509_create/; # ignore for now
76 if (!$skip && $line =~ m/^#define/)
78 $splitDefine = 1 if $line =~ m/\\$/;
81 # check line is not split
82 next if $splitDefine == 1;
85 # pick up second line of #define statement
90 # check line is not split
91 $splitDefine = ($line =~ m/\\$/);
95 # test for function declaration
96 if (!$skip && $line =~ /EXP_FUNC/ && $line !~/\/\
*/)
98 $line = transformSignature
($line);
99 $splitFunctionDeclaration = $line !~ /;/;
100 print DATA_OUT
$line;
104 if ($splitFunctionDeclaration)
106 $line = transformSignature
($line);
107 $splitFunctionDeclaration = $line !~ /;/;
108 print DATA_OUT
$line;
114 #===============================================================
116 # Determine which module to build from cammand-line options
127 if (not defined $ARGV[0])
132 if ($ARGV[0] eq "-java")
134 print "Generating Java interface file\n";
136 $interfaceFile = "java/axTLSj.i";
138 elsif ($ARGV[0] eq "-perl")
140 print "Generating Perl interface file\n";
142 $interfaceFile = "perl/axTLSp.i";
144 elsif ($ARGV[0] eq "-lua")
146 print "Generating lua interface file\n";
148 $interfaceFile = "lua/axTLSl.i";
153 die "Usage: $0 [-java | -perl | -lua]\n";
156 # Input file required to generate SWIG interface file.
157 $data_file = "../ssl/ssl.h";
160 open(DATA_IN
, $data_file) || die("Could not open file ($data_file)!");
161 @raw_data = <DATA_IN
>;
164 open(DATA_OUT
, ">$interfaceFile") || die("Cannot Open File");
167 # I wish I could say it was easy to generate the Perl/Java/Lua bindings,
168 # but each had their own set of challenges... :-(.
170 print DATA_OUT
<< "END";
173 /* include our own header */
178 %include "typemaps.i"
179 /* Some SWIG magic to make the API a bit more Java friendly */
182 %apply long
{ SSL
* };
183 %apply long
{ SSL_CTX
* };
184 %apply long
{ SSLObjLoader
* };
186 /* allow "unsigned char []" to become "byte[]" */
187 %include "arrays_java.i"
189 /* convert these pointers to use long */
190 %apply signed char
[] {unsigned char
*};
191 %apply signed char
[] {signed char
*};
193 /* allow ssl_get_session_id() to return "byte[]" */
194 %typemap(out
) unsigned char
* ssl_get_session_id
\"if (result
) jresult
= SWIG_JavaArrayOutSchar
(jenv
, result
, ssl_get_session_id_size
((SSL const
*)arg1
));\"
196 /* allow ssl_client_new() to have a null session_id input */
197 %typemap(in) const signed char session_id
[] (jbyte
*jarr
) {
200 jresult
= (jint
)ssl_client_new
(arg1
,arg2
,NULL
,0);
204 if (!SWIG_JavaArrayInSchar
(jenv
, &jarr
, &arg3
, jarg3
)) return 0;
207 /* Lot
's of work required for an ssl_read() due to its various custom
210 %native (ssl_read) int ssl_read(SSL *ssl, jobject in_data);
212 JNIEXPORT jint JNICALL Java_axTLSj_axtlsjJNI_ssl_1read(JNIEnv *jenv, jclass jcls, jint jarg1, jobject jarg2) {
223 result = (int)ssl_read(arg1, &arg2);
225 /* find the "m_buf" entry in the SSLReadHolder class */
226 if (!(holder_class = e->GetObjectClass(jenv,jarg2)) ||
227 !(fid = e->GetFieldID(jenv,holder_class, "m_buf", "[B")))
234 /* create a new byte array to hold the read data */
235 jbyteArray jarray = e->NewByteArray(jenv, result);
237 /* copy the bytes across to the java byte array */
238 jarr = e->GetByteArrayElements(jenv, jarray, 0);
239 for (i = 0; i < result; i++)
240 jarr[i] = (jbyte)arg2[i];
242 /* clean up and set the new m_buf object */
243 e->ReleaseByteArrayElements(jenv, jarray, jarr, 0);
244 e->SetObjectField(jenv, jarg2, fid, jarray);
246 else /* set to null */
247 e->SetObjectField(jenv, jarg2, fid, NULL);
249 jresult = (jint)result;
254 /* Big hack to get hold of a socket's file descriptor
*/
255 %typemap (jtype
) long
"Object"
256 %typemap (jstype
) long
"Object"
257 %native (getFd
) int getFd
(long sock
);
259 JNIEXPORT jint JNICALL Java_axTLSj_axtlsjJNI_getFd
(JNIEnv
*env
, jclass jcls
, jobject sock
)
266 /* get the SocketImpl from the Socket */
267 if (!(jcls
= e
->GetObjectClass(env
,sock
)) ||
268 !(fid
= e
->GetFieldID(env
,jcls
,"impl","Ljava/net/SocketImpl;")) ||
269 !(impl
= e
->GetObjectField(env
,sock
,fid
))) return -1;
271 /* get the FileDescriptor from the SocketImpl */
272 if (!(jcls
= e
->GetObjectClass(env
,impl
)) ||
273 !(fid
= e
->GetFieldID(env
,jcls
,"fd","Ljava/io/FileDescriptor;")) ||
274 !(fdesc
= e
->GetObjectField(env
,impl
,fid
))) return -1;
276 /* get the fd from the FileDescriptor */
277 if (!(jcls
= e
->GetObjectClass(env
,fdesc
)) ||
278 !(fid
= e
->GetFieldID(env
,jcls
,"fd","I"))) return -1;
280 /* return the descriptor */
281 return e
->GetIntField(env
,fdesc
,fid
);
287 /* Some SWIG magic to make the API a bit more Perl friendly */
290 /* for ssl_session_id() */
291 %typemap(out
) const unsigned char
* {
292 SV
*svs
= newSVpv
((unsigned char
*)\
$1, ssl_get_session_id_size
((SSL const
*)arg1
));
293 \
$result = newRV
(svs
);
294 sv_2mortal
(\
$result);
298 /* for ssl_write() */
299 %typemap(in) const unsigned char out_data
[] {
302 croak
("Argument \$argnum is not a reference.");
303 tempsv
= SvRV
(\
$input);
304 if (SvTYPE
(tempsv
) != SVt_PV
)
305 croak
("Argument \$argnum is not an string.");
306 \
$1 = (unsigned char
*)SvPV
(tempsv
, PL_na
);
310 %typemap(in) unsigned char
**in_data
(unsigned char
*buf
) {
314 %typemap(argout
) unsigned char
**in_data
{
315 if (result
> SSL_OK
) {
316 SV
*svs
= newSVpv
(*\
$1, result
);
317 \
$result = newRV
(svs
);
318 sv_2mortal
(\
$result);
323 /* for ssl_client_new() */
324 %typemap(in) const unsigned char session_id
[] {
325 /* check for a reference */
326 if (SvOK
(\
$input) && SvROK
(\
$input)) {
327 SV
* tempsv
= SvRV
(\
$input);
328 if (SvTYPE
(tempsv
) != SVt_PV
)
329 croak
("Argument \$argnum is not an string.");
330 \
$1 = (unsigned char
*)SvPV
(tempsv
, PL_na
);
338 /* Some SWIG magic to make the API a bit more Lua friendly */
340 SWIG_NUMBER_TYPEMAP
(unsigned char
);
341 SWIG_TYPEMAP_NUM_ARR
(uchar
,unsigned char
);
343 /* for ssl_session_id() */
344 %typemap(out
) const unsigned char
* {
347 for (i
= 0; i
< ssl_get_session_id_size
((SSL const
*)arg1
); i
++){
348 lua_pushnumber
(L
,(lua_Number
)result
[i
]);
349 lua_rawseti
(L
,-2,i
+1); /* -1 is the number, -2 is the table */
355 %typemap(in) unsigned char
**in_data
(unsigned char
*buf
) {
359 %typemap(argout
) unsigned char
**in_data
{
360 if (result
> SSL_OK
) {
363 for (i
= 0; i
< result
; i
++){
364 lua_pushnumber
(L
,(lua_Number
)buf2
[i
]);
365 lua_rawseti
(L
,-2,i
+1); /* -1 is the number, -2 is the table */
371 /* for ssl_client_new() */
372 %typemap(in) const unsigned char session_id
[] {
373 if (lua_isnil
(L
,\
$input))
376 \
$1 = SWIG_get_uchar_num_array_fixed
(L
,\
$input, ssl_get_session_id
((SSL const
*)\
$1));
383 # Initialise loop variables
387 parseFile
(@raw_data);
392 #===============================================================