File: Rpc_intro.html

package info (click to toggle)
ocamlnet 4.1.9-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 54,040 kB
  • sloc: ml: 151,939; ansic: 11,071; sh: 2,003; makefile: 1,310
file content (1215 lines) | stat: -rw-r--r-- 64,196 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="style.css" type="text/css">
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="Start" href="index.html">
<link rel="previous" href="Rpc_proxy.html">
<link rel="next" href="Rpc_mapping_ref.html">
<link rel="Up" href="index.html">
<link title="Index of types" rel=Appendix href="index_types.html">
<link title="Index of extensions" rel=Appendix href="index_extensions.html">
<link title="Index of exceptions" rel=Appendix href="index_exceptions.html">
<link title="Index of values" rel=Appendix href="index_values.html">
<link title="Index of class attributes" rel=Appendix href="index_attributes.html">
<link title="Index of class methods" rel=Appendix href="index_methods.html">
<link title="Index of classes" rel=Appendix href="index_classes.html">
<link title="Index of class types" rel=Appendix href="index_class_types.html">
<link title="Index of modules" rel=Appendix href="index_modules.html">
<link title="Index of module types" rel=Appendix href="index_module_types.html">
<link title="Uq_gtk" rel="Chapter" href="Uq_gtk.html">
<link title="Uq_tcl" rel="Chapter" href="Uq_tcl.html">
<link title="Equeue" rel="Chapter" href="Equeue.html">
<link title="Unixqueue" rel="Chapter" href="Unixqueue.html">
<link title="Unixqueue_pollset" rel="Chapter" href="Unixqueue_pollset.html">
<link title="Unixqueue_select" rel="Chapter" href="Unixqueue_select.html">
<link title="Uq_resolver" rel="Chapter" href="Uq_resolver.html">
<link title="Uq_engines" rel="Chapter" href="Uq_engines.html">
<link title="Uq_multiplex" rel="Chapter" href="Uq_multiplex.html">
<link title="Uq_transfer" rel="Chapter" href="Uq_transfer.html">
<link title="Uq_socks5" rel="Chapter" href="Uq_socks5.html">
<link title="Uq_io" rel="Chapter" href="Uq_io.html">
<link title="Uq_lwt" rel="Chapter" href="Uq_lwt.html">
<link title="Uq_libevent" rel="Chapter" href="Uq_libevent.html">
<link title="Uq_mt" rel="Chapter" href="Uq_mt.html">
<link title="Uq_client" rel="Chapter" href="Uq_client.html">
<link title="Uq_server" rel="Chapter" href="Uq_server.html">
<link title="Uq_datagram" rel="Chapter" href="Uq_datagram.html">
<link title="Uq_engines_compat" rel="Chapter" href="Uq_engines_compat.html">
<link title="Equeue_intro" rel="Chapter" href="Equeue_intro.html">
<link title="Equeue_howto" rel="Chapter" href="Equeue_howto.html">
<link title="Netcamlbox" rel="Chapter" href="Netcamlbox.html">
<link title="Netcgi_apache" rel="Chapter" href="Netcgi_apache.html">
<link title="Netcgi_modtpl" rel="Chapter" href="Netcgi_modtpl.html">
<link title="Netcgi_plex" rel="Chapter" href="Netcgi_plex.html">
<link title="Netcgi_common" rel="Chapter" href="Netcgi_common.html">
<link title="Netcgi" rel="Chapter" href="Netcgi.html">
<link title="Netcgi_ajp" rel="Chapter" href="Netcgi_ajp.html">
<link title="Netcgi_scgi" rel="Chapter" href="Netcgi_scgi.html">
<link title="Netcgi_cgi" rel="Chapter" href="Netcgi_cgi.html">
<link title="Netcgi_fcgi" rel="Chapter" href="Netcgi_fcgi.html">
<link title="Netcgi_dbi" rel="Chapter" href="Netcgi_dbi.html">
<link title="Netcgi1_compat" rel="Chapter" href="Netcgi1_compat.html">
<link title="Netcgi_test" rel="Chapter" href="Netcgi_test.html">
<link title="Netcgi_porting" rel="Chapter" href="Netcgi_porting.html">
<link title="Nethttp_client_conncache" rel="Chapter" href="Nethttp_client_conncache.html">
<link title="Nethttp_client" rel="Chapter" href="Nethttp_client.html">
<link title="Nettelnet_client" rel="Chapter" href="Nettelnet_client.html">
<link title="Netftp_data_endpoint" rel="Chapter" href="Netftp_data_endpoint.html">
<link title="Netftp_client" rel="Chapter" href="Netftp_client.html">
<link title="Nethttp_fs" rel="Chapter" href="Nethttp_fs.html">
<link title="Netftp_fs" rel="Chapter" href="Netftp_fs.html">
<link title="Netsmtp" rel="Chapter" href="Netsmtp.html">
<link title="Netpop" rel="Chapter" href="Netpop.html">
<link title="Netldap" rel="Chapter" href="Netldap.html">
<link title="Netclient_tut" rel="Chapter" href="Netclient_tut.html">
<link title="Netgss_bindings" rel="Chapter" href="Netgss_bindings.html">
<link title="Netgss" rel="Chapter" href="Netgss.html">
<link title="Nethttpd_types" rel="Chapter" href="Nethttpd_types.html">
<link title="Nethttpd_kernel" rel="Chapter" href="Nethttpd_kernel.html">
<link title="Nethttpd_reactor" rel="Chapter" href="Nethttpd_reactor.html">
<link title="Nethttpd_engine" rel="Chapter" href="Nethttpd_engine.html">
<link title="Nethttpd_services" rel="Chapter" href="Nethttpd_services.html">
<link title="Nethttpd_plex" rel="Chapter" href="Nethttpd_plex.html">
<link title="Nethttpd_util" rel="Chapter" href="Nethttpd_util.html">
<link title="Nethttpd_intro" rel="Chapter" href="Nethttpd_intro.html">
<link title="Netmcore" rel="Chapter" href="Netmcore.html">
<link title="Netmcore_camlbox" rel="Chapter" href="Netmcore_camlbox.html">
<link title="Netmcore_mempool" rel="Chapter" href="Netmcore_mempool.html">
<link title="Netmcore_heap" rel="Chapter" href="Netmcore_heap.html">
<link title="Netmcore_ref" rel="Chapter" href="Netmcore_ref.html">
<link title="Netmcore_array" rel="Chapter" href="Netmcore_array.html">
<link title="Netmcore_sem" rel="Chapter" href="Netmcore_sem.html">
<link title="Netmcore_mutex" rel="Chapter" href="Netmcore_mutex.html">
<link title="Netmcore_condition" rel="Chapter" href="Netmcore_condition.html">
<link title="Netmcore_queue" rel="Chapter" href="Netmcore_queue.html">
<link title="Netmcore_buffer" rel="Chapter" href="Netmcore_buffer.html">
<link title="Netmcore_matrix" rel="Chapter" href="Netmcore_matrix.html">
<link title="Netmcore_hashtbl" rel="Chapter" href="Netmcore_hashtbl.html">
<link title="Netmcore_process" rel="Chapter" href="Netmcore_process.html">
<link title="Netmcore_tut" rel="Chapter" href="Netmcore_tut.html">
<link title="Netmcore_basics" rel="Chapter" href="Netmcore_basics.html">
<link title="Netplex_types" rel="Chapter" href="Netplex_types.html">
<link title="Netplex_mp" rel="Chapter" href="Netplex_mp.html">
<link title="Netplex_mt" rel="Chapter" href="Netplex_mt.html">
<link title="Netplex_log" rel="Chapter" href="Netplex_log.html">
<link title="Netplex_controller" rel="Chapter" href="Netplex_controller.html">
<link title="Netplex_container" rel="Chapter" href="Netplex_container.html">
<link title="Netplex_sockserv" rel="Chapter" href="Netplex_sockserv.html">
<link title="Netplex_workload" rel="Chapter" href="Netplex_workload.html">
<link title="Netplex_main" rel="Chapter" href="Netplex_main.html">
<link title="Netplex_config" rel="Chapter" href="Netplex_config.html">
<link title="Netplex_kit" rel="Chapter" href="Netplex_kit.html">
<link title="Rpc_netplex" rel="Chapter" href="Rpc_netplex.html">
<link title="Netplex_cenv" rel="Chapter" href="Netplex_cenv.html">
<link title="Netplex_semaphore" rel="Chapter" href="Netplex_semaphore.html">
<link title="Netplex_sharedvar" rel="Chapter" href="Netplex_sharedvar.html">
<link title="Netplex_mutex" rel="Chapter" href="Netplex_mutex.html">
<link title="Netplex_encap" rel="Chapter" href="Netplex_encap.html">
<link title="Netplex_mbox" rel="Chapter" href="Netplex_mbox.html">
<link title="Netplex_internal" rel="Chapter" href="Netplex_internal.html">
<link title="Netplex_intro" rel="Chapter" href="Netplex_intro.html">
<link title="Netplex_advanced" rel="Chapter" href="Netplex_advanced.html">
<link title="Netplex_admin" rel="Chapter" href="Netplex_admin.html">
<link title="Netshm" rel="Chapter" href="Netshm.html">
<link title="Netshm_data" rel="Chapter" href="Netshm_data.html">
<link title="Netshm_hashtbl" rel="Chapter" href="Netshm_hashtbl.html">
<link title="Netshm_array" rel="Chapter" href="Netshm_array.html">
<link title="Netshm_intro" rel="Chapter" href="Netshm_intro.html">
<link title="Netstring_pcre" rel="Chapter" href="Netstring_pcre.html">
<link title="Netconversion" rel="Chapter" href="Netconversion.html">
<link title="Netchannels" rel="Chapter" href="Netchannels.html">
<link title="Netstream" rel="Chapter" href="Netstream.html">
<link title="Netmime_string" rel="Chapter" href="Netmime_string.html">
<link title="Netmime" rel="Chapter" href="Netmime.html">
<link title="Netsendmail" rel="Chapter" href="Netsendmail.html">
<link title="Neturl" rel="Chapter" href="Neturl.html">
<link title="Netaddress" rel="Chapter" href="Netaddress.html">
<link title="Netbuffer" rel="Chapter" href="Netbuffer.html">
<link title="Netmime_header" rel="Chapter" href="Netmime_header.html">
<link title="Netmime_channels" rel="Chapter" href="Netmime_channels.html">
<link title="Neturl_ldap" rel="Chapter" href="Neturl_ldap.html">
<link title="Netdate" rel="Chapter" href="Netdate.html">
<link title="Netencoding" rel="Chapter" href="Netencoding.html">
<link title="Netulex" rel="Chapter" href="Netulex.html">
<link title="Netaccel" rel="Chapter" href="Netaccel.html">
<link title="Netaccel_link" rel="Chapter" href="Netaccel_link.html">
<link title="Nethtml" rel="Chapter" href="Nethtml.html">
<link title="Netstring_str" rel="Chapter" href="Netstring_str.html">
<link title="Netmappings" rel="Chapter" href="Netmappings.html">
<link title="Netaux" rel="Chapter" href="Netaux.html">
<link title="Nethttp" rel="Chapter" href="Nethttp.html">
<link title="Netpagebuffer" rel="Chapter" href="Netpagebuffer.html">
<link title="Netfs" rel="Chapter" href="Netfs.html">
<link title="Netglob" rel="Chapter" href="Netglob.html">
<link title="Netauth" rel="Chapter" href="Netauth.html">
<link title="Netsockaddr" rel="Chapter" href="Netsockaddr.html">
<link title="Netnumber" rel="Chapter" href="Netnumber.html">
<link title="Netxdr_mstring" rel="Chapter" href="Netxdr_mstring.html">
<link title="Netxdr" rel="Chapter" href="Netxdr.html">
<link title="Netcompression" rel="Chapter" href="Netcompression.html">
<link title="Netunichar" rel="Chapter" href="Netunichar.html">
<link title="Netasn1" rel="Chapter" href="Netasn1.html">
<link title="Netasn1_encode" rel="Chapter" href="Netasn1_encode.html">
<link title="Netoid" rel="Chapter" href="Netoid.html">
<link title="Netstring_tstring" rel="Chapter" href="Netstring_tstring.html">
<link title="Netdn" rel="Chapter" href="Netdn.html">
<link title="Netx509" rel="Chapter" href="Netx509.html">
<link title="Netascii_armor" rel="Chapter" href="Netascii_armor.html">
<link title="Nettls_support" rel="Chapter" href="Nettls_support.html">
<link title="Netmech_scram" rel="Chapter" href="Netmech_scram.html">
<link title="Netmech_scram_gssapi" rel="Chapter" href="Netmech_scram_gssapi.html">
<link title="Netmech_scram_sasl" rel="Chapter" href="Netmech_scram_sasl.html">
<link title="Netmech_scram_http" rel="Chapter" href="Netmech_scram_http.html">
<link title="Netgssapi_support" rel="Chapter" href="Netgssapi_support.html">
<link title="Netgssapi_auth" rel="Chapter" href="Netgssapi_auth.html">
<link title="Netchannels_crypto" rel="Chapter" href="Netchannels_crypto.html">
<link title="Netx509_pubkey" rel="Chapter" href="Netx509_pubkey.html">
<link title="Netx509_pubkey_crypto" rel="Chapter" href="Netx509_pubkey_crypto.html">
<link title="Netsaslprep" rel="Chapter" href="Netsaslprep.html">
<link title="Netmech_plain_sasl" rel="Chapter" href="Netmech_plain_sasl.html">
<link title="Netmech_crammd5_sasl" rel="Chapter" href="Netmech_crammd5_sasl.html">
<link title="Netmech_digest_sasl" rel="Chapter" href="Netmech_digest_sasl.html">
<link title="Netmech_digest_http" rel="Chapter" href="Netmech_digest_http.html">
<link title="Netmech_krb5_sasl" rel="Chapter" href="Netmech_krb5_sasl.html">
<link title="Netmech_gs2_sasl" rel="Chapter" href="Netmech_gs2_sasl.html">
<link title="Netmech_spnego_http" rel="Chapter" href="Netmech_spnego_http.html">
<link title="Netchannels_tut" rel="Chapter" href="Netchannels_tut.html">
<link title="Netmime_tut" rel="Chapter" href="Netmime_tut.html">
<link title="Netsendmail_tut" rel="Chapter" href="Netsendmail_tut.html">
<link title="Netulex_tut" rel="Chapter" href="Netulex_tut.html">
<link title="Neturl_tut" rel="Chapter" href="Neturl_tut.html">
<link title="Netsys" rel="Chapter" href="Netsys.html">
<link title="Netsys_posix" rel="Chapter" href="Netsys_posix.html">
<link title="Netsys_pollset" rel="Chapter" href="Netsys_pollset.html">
<link title="Netlog" rel="Chapter" href="Netlog.html">
<link title="Netexn" rel="Chapter" href="Netexn.html">
<link title="Netsys_win32" rel="Chapter" href="Netsys_win32.html">
<link title="Netsys_pollset_posix" rel="Chapter" href="Netsys_pollset_posix.html">
<link title="Netsys_pollset_win32" rel="Chapter" href="Netsys_pollset_win32.html">
<link title="Netsys_pollset_generic" rel="Chapter" href="Netsys_pollset_generic.html">
<link title="Netsys_signal" rel="Chapter" href="Netsys_signal.html">
<link title="Netsys_oothr" rel="Chapter" href="Netsys_oothr.html">
<link title="Netsys_xdr" rel="Chapter" href="Netsys_xdr.html">
<link title="Netsys_rng" rel="Chapter" href="Netsys_rng.html">
<link title="Netsys_crypto_types" rel="Chapter" href="Netsys_crypto_types.html">
<link title="Netsys_types" rel="Chapter" href="Netsys_types.html">
<link title="Netsys_mem" rel="Chapter" href="Netsys_mem.html">
<link title="Netsys_tmp" rel="Chapter" href="Netsys_tmp.html">
<link title="Netsys_sem" rel="Chapter" href="Netsys_sem.html">
<link title="Netsys_pmanage" rel="Chapter" href="Netsys_pmanage.html">
<link title="Netsys_crypto" rel="Chapter" href="Netsys_crypto.html">
<link title="Netsys_tls" rel="Chapter" href="Netsys_tls.html">
<link title="Netsys_ciphers" rel="Chapter" href="Netsys_ciphers.html">
<link title="Netsys_digests" rel="Chapter" href="Netsys_digests.html">
<link title="Netsys_crypto_modes" rel="Chapter" href="Netsys_crypto_modes.html">
<link title="Netsys_gssapi" rel="Chapter" href="Netsys_gssapi.html">
<link title="Netsys_sasl_types" rel="Chapter" href="Netsys_sasl_types.html">
<link title="Netsys_sasl" rel="Chapter" href="Netsys_sasl.html">
<link title="Netsys_polypipe" rel="Chapter" href="Netsys_polypipe.html">
<link title="Netsys_polysocket" rel="Chapter" href="Netsys_polysocket.html">
<link title="Netsys_global" rel="Chapter" href="Netsys_global.html">
<link title="Nettls_gnutls_bindings" rel="Chapter" href="Nettls_gnutls_bindings.html">
<link title="Nettls_nettle_bindings" rel="Chapter" href="Nettls_nettle_bindings.html">
<link title="Nettls_gnutls" rel="Chapter" href="Nettls_gnutls.html">
<link title="Netunidata" rel="Chapter" href="Netunidata.html">
<link title="Netgzip" rel="Chapter" href="Netgzip.html">
<link title="Rpc_auth_local" rel="Chapter" href="Rpc_auth_local.html">
<link title="Rpc_xti_client" rel="Chapter" href="Rpc_xti_client.html">
<link title="Rpc" rel="Chapter" href="Rpc.html">
<link title="Rpc_program" rel="Chapter" href="Rpc_program.html">
<link title="Rpc_util" rel="Chapter" href="Rpc_util.html">
<link title="Rpc_portmapper_aux" rel="Chapter" href="Rpc_portmapper_aux.html">
<link title="Rpc_packer" rel="Chapter" href="Rpc_packer.html">
<link title="Rpc_transport" rel="Chapter" href="Rpc_transport.html">
<link title="Rpc_client" rel="Chapter" href="Rpc_client.html">
<link title="Rpc_simple_client" rel="Chapter" href="Rpc_simple_client.html">
<link title="Rpc_portmapper_clnt" rel="Chapter" href="Rpc_portmapper_clnt.html">
<link title="Rpc_portmapper" rel="Chapter" href="Rpc_portmapper.html">
<link title="Rpc_server" rel="Chapter" href="Rpc_server.html">
<link title="Rpc_auth_sys" rel="Chapter" href="Rpc_auth_sys.html">
<link title="Rpc_auth_gssapi" rel="Chapter" href="Rpc_auth_gssapi.html">
<link title="Rpc_proxy" rel="Chapter" href="Rpc_proxy.html">
<link title="Rpc_intro" rel="Chapter" href="Rpc_intro.html">
<link title="Rpc_mapping_ref" rel="Chapter" href="Rpc_mapping_ref.html">
<link title="Rpc_intro_gss" rel="Chapter" href="Rpc_intro_gss.html">
<link title="Shell_sys" rel="Chapter" href="Shell_sys.html">
<link title="Shell" rel="Chapter" href="Shell.html">
<link title="Shell_uq" rel="Chapter" href="Shell_uq.html">
<link title="Shell_fs" rel="Chapter" href="Shell_fs.html">
<link title="Shell_intro" rel="Chapter" href="Shell_intro.html">
<link title="Intro" rel="Chapter" href="Intro.html">
<link title="Platform" rel="Chapter" href="Platform.html">
<link title="Foreword" rel="Chapter" href="Foreword.html">
<link title="Ipv6" rel="Chapter" href="Ipv6.html">
<link title="Regexp" rel="Chapter" href="Regexp.html">
<link title="Tls" rel="Chapter" href="Tls.html">
<link title="Crypto" rel="Chapter" href="Crypto.html">
<link title="Authentication" rel="Chapter" href="Authentication.html">
<link title="Credentials" rel="Chapter" href="Credentials.html">
<link title="Gssapi" rel="Chapter" href="Gssapi.html">
<link title="Ocamlnet4" rel="Chapter" href="Ocamlnet4.html">
<link title="Get" rel="Chapter" href="Get.html"><title>Ocamlnet 4 Reference Manual : Rpc_intro</title>
</head>
<body>
<div class="navbar"><a class="pre" href="Rpc_proxy.html" title="Rpc_proxy">Previous</a>
&nbsp;<a class="up" href="index.html" title="Index">Up</a>
&nbsp;<a class="post" href="Rpc_mapping_ref.html" title="Rpc_mapping_ref">Next</a>
</div>
<h1>Rpc_intro</h1>
<div class="info-desc">
<p><b>Contents</b></p>
<ul>
<li><code class="code">Rpc_intro.intro</code>
    <ul>
<li><code class="code">Rpc_intro.intro_clnt</code></li>
<li><code class="code">Rpc_intro.intro_srv</code></li>
</ul>

  </li>
<li><code class="code">Rpc_intro.rpcgen</code></li>
<li><code class="code">Rpc_intro.mapping</code>
    <ul>
<li><code class="code">Rpc_intro.syn_xdr</code></li>
<li><code class="code">Rpc_intro.syn_prog</code></li>
<li><code class="code">Rpc_intro.map_names</code></li>
<li><code class="code">Rpc_intro.map_ints</code></li>
<li><code class="code">Rpc_intro.map_fps</code></li>
<li><code class="code">Rpc_intro.map_strings</code></li>
<li><code class="code">Rpc_intro.map_arrays</code></li>
<li><code class="code">Rpc_intro.map_records</code></li>
<li><code class="code">Rpc_intro.map_enums</code></li>
<li><code class="code">Rpc_intro.map_eunions</code></li>
<li><code class="code">Rpc_intro.map_iunions</code></li>
<li><code class="code">Rpc_intro.map_opts</code></li>
<li><code class="code">Rpc_intro.map_recs</code></li>
</ul>

  </li>
<li><code class="code">Rpc_intro.lib</code></li>
<li><code class="code">Rpc_intro.rpc_netplex</code></li>
<li><code class="code">Rpc_intro.restrictions</code></li>
</ul>

<h2 id="intro">Introduction to <code class="code">ocamlrpcgen</code></h2>
<p>The tool <code class="code">ocamlrpcgen</code> generates O'Caml modules which greatly simplify
the creation and invocation of remote procedures. For example, if we have an
XDR definition file <code class="code">calculate.x</code></p>

<pre class="codepre"><code class="code">program P {
  version V {
    int add(int,int) = 1;
  } = 2;
} = 3;
</code></pre>
<p>the generation of a corresponding RPC client is done by issuing the command</p>

<pre class="codepre"><code class="code">ocamlrpcgen -aux -clnt calculate.x
</code></pre>
<p>and the tool will generate an RPC server by calling</p>

<pre class="codepre"><code class="code">ocamlrpcgen -aux -srv calculate.x
</code></pre>
<p>The flag -aux causes <code class="code">ocamlrpcgen</code> to create a module <code class="code">Calculate_aux</code>
containing types, and constants from the XDR definition, and
containing conversion functions doing the language mapping from XDR to
O'Caml and vice versa.</p>

<p><code class="code">Calculate_aux</code> defines the types for the arguments of the procedure and
the result as follows:</p>

<pre class="codepre"><code class="code">type t_P'V'add'arg =                      (* Arguments *)
      ( Netnumber.int4 * Netnumber.int4 )
and t_P'V'add'res =                       (* Result *)
      Netnumber.int4
</code></pre>
<p>Note that the XDR integer type is mapped to <a href="Netnumber.html#TYPEint4"><code class="code">Netnumber.int4</code></a> which is an
opaque type representing 4-byte signed integers. <a href="Netnumber.html"><code class="code">Netnumber</code></a> defines
conversion functions for int4 to/from other O'Caml types. If
<a href="Netnumber.html#TYPEint4"><code class="code">Netnumber.int4</code></a> is not what you want, you can select a different
integer mapping on the command line of <code class="code">ocamlrpcgen</code>. For example, <code class="code">-int
int32</code> selects that you want the built-in <code class="code">int32</code> integer type, and <code class="code">-int
unboxed</code> selects that you want the built-in <code class="code">int</code> integer type. Note (1)
that you can also select the integer mapping case-by-case (see below),
and (2) that there is a corresponding switch for the XDR <code class="code">hyper</code> type
(8-byte integers).</p>

<p><code class="code">Calculate_aux</code> also defines constants (none in our example), conversion
functions, XDR type terms, and RPC programs. These other kinds of definitions
can be ignored for the moment.</p>

<h3 id="intro_clnt">Generating clients with <code class="code">ocamlrpcgen</code></h3>
<p>The flag <code class="code">-clnt</code> causes <code class="code">ocamlrpcgen</code> to generate the module
<code class="code">Calculate_clnt</code> containing functions necessary to contact a remote
program as client. Here, <code class="code">Calculate_clnt</code> has the signature:</p>

<pre class="codepre"><code class="code">module P : sig
  module V : sig
    open Calculate_aux
    val create_client :
            ?esys:Unixqueue.event_system -&gt;
            Rpc_client.connector -&gt;
            Rpc.protocol -&gt;
            Rpc_client.t
    val create_portmapped_client :
            ?esys:Unixqueue.event_system -&gt;
            string -&gt;
            Rpc.protocol -&gt;
            Rpc_client.t
    val add : Rpc_client.t -&gt; t_P'V'add'arg -&gt; t_P'V'add'res
    val add'async :
            Rpc_client.t -&gt;
            t_P'V'add'arg -&gt;
            ((unit -&gt; t_P'V'add'res) -&gt; unit) -&gt;
            unit
  end
end
</code></pre>
<p>(Note: Depending on the version of <code class="code">ocamlrpcgen</code> your are using,
another function <code class="code">create_client2</code> may also be generated.)</p>

<p>Normally, the function <code class="code">P.V.create_portmapped_client</code> is the preferred
function to contact the RPC program. For example, to call the <code class="code">add</code>
procedure running on host <code class="code">moon</code>, the following statements suffice:</p>

<pre class="codepre"><code class="code">let m1 = 42 in
let m2 = 36 in
let client = Calculator_clnt.P.V.create_portmapped_client "moon" Rpc.Tcp in
let n = Calculator_clnt.P.V.add client (m1,m2) in
Rpc_client.shut_down client;
</code></pre>
<p>That's all for a simple client!</p>

<p>The invocation of <code class="code">P.V.create_portmapped_client</code> first asks the
portmapper on "moon" for the TCP instance of the program <code class="code">P.V</code>, and
stores the resulting internet port. Because we wanted TCP, the TCP
connection is opened, too. When <code class="code">P.V.add</code> is called, the values <code class="code">m1</code> and
<code class="code">m2</code> are XDR-encoded and sent over the TCP connection to the remote
procedure; the answer is XDR-decoded and returned, here <code class="code">n</code>. Finally,
the function <code class="code">Rpc_client.shut_down</code> closes the TCP connection.</p>

<p>Of course, this works for UDP transports, too; simply pass <code class="code">Rpc.Udp</code>
instead of <code class="code">Rpc.Tcp</code>.</p>

<p>The function <code class="code">P.V.create_client</code> does not contact the portmapper to
find out the internet port; you must already know the port and pass it
as connector argument (see <a href="Rpc_client.html"><code class="code">Rpc_client</code></a> for details).</p>

<p>You could have also invoked <code class="code">add</code> in an asynchronous way by using
<code class="code">P.V.add'async</code>. This function does not wait until the result of the
RPC call arrives; it returns immediately. When the result value has
been received, the function passed as third argument is called back,
and can process the value. An application of asynchronous calls is to
invoke two remote procedures at the same time:</p>

<pre class="codepre"><code class="code">let esys = Unixqueue.create_event_system() in
let client1 = Calculator_clnt.P.V.create_portmapped_client 
                ~esys:esys "moon" Rpc.Tcp in
let client2 = Calculator_clnt.P.V.create_portmapped_client 
                ~esys:esys "mars" Rpc.Tcp in
let got_answer1 get_value =
  let v = get_value() in
  print_endline "moon has replied!"; ... in
let got_answer2 get_value =
  let v = get_value() in
  print_endline "mars has replied!"; ... in
Calculator_clnt.P.V.add'async client1 (m1,m2) got_answer1;
Calculator_clnt.P.V.add'async client2 (m3,m4) got_answer1;
Unixqueue.run esys
</code></pre>
<p>Here, the two clients can coexist because they share the same event
system (see the <a href="Unixqueue.html"><code class="code">Unixqueue</code></a> module); this system manages it that
every network event on the connection to "moon" will be forwarded to
<code class="code">client1</code> and that the network events on the connection to "mars" will
be forwarded to <code class="code">client2</code>. The <code class="code">add'async</code> calls do not block; they
only register themselves with the event system and return
immediately. <a href="Unixqueue.html#VALrun"><code class="code">Unixqueue.run</code></a> starts the event system: The XDR-encoded
values <code class="code">(m1,m2)</code> are sent to "moon", and <code class="code">(m3,m4)</code> to "mars"; replies
are recorded. Once the reply of "moon" is complete, <code class="code">got_answer1</code> is
called; once the reply of "mars" has been fully received,
<code class="code">got_answer2</code> is called. These functions can now query the received
values by invoking <code class="code">get_value</code>; note that <code class="code">get_value</code> will either
return the value or raise an exception if something went wrong. When
both answers have been received and processed, <a href="Unixqueue.html#VALrun"><code class="code">Unixqueue.run</code></a> will
return.</p>

<p>Obviously, asynchronous clients are a bit more complicated than
synchronous ones; however it is still rather simple to program them. For
more information on how the event handling works, see <a href="Equeue_intro.html"><code class="code">Equeue_intro</code></a>.</p>

<p>Note that clients have only a limited lifetime: After a shutdown or an
error they become unusable. Since Ocamlnet version 3 there is another
flavor of client, the so-called proxies. See <a href="Rpc_proxy.html#tut"><i>The Rpc_proxy tutorial</i></a> for an
introduction. In particular, proxies can reconnect the connection to
the server after a shutdown, and they can even manage several
connections to the same server, or to different servers that are seen
as equivalent.</p>

<h3 id="intro_srv">Generating servers with <code class="code">ocamlrpcgen</code></h3>
<p>The flag <code class="code">-srv</code> causes <code class="code">ocamlrpcgen</code> to generate the module
<code class="code">Calculate_srv</code> containing functions which can act as RPC
servers. (Note: Recent versions of <code class="code">ocamlrpcgen</code> also support a switch
<code class="code">-srv2</code> that generates slightly better server stubs where one can bind
several programs/versions to the same server port.) Here,
<code class="code">Calculate_srv</code> has the signature:</p>

<pre class="codepre"><code class="code">module P : sig
  module V : sig
    open Calculate_aux
    val create_server :
            ?limit:int -&gt;
            proc_add : (t_P'V'add'arg -&gt; t_P'V'add'res) -&gt;
            Rpc_server.connector -&gt;
            Rpc.protocol -&gt;
            Rpc.mode -&gt;
            Unixqueue.event_system -&gt;
            Rpc_server.t
    val create_async_server :
            ?limit:int -&gt;
            proc_add : (Rpc_server.session -&gt;
                        t_P'V'add'arg -&gt;
                        (t_P'V'add'res -&gt; unit) -&gt;
                        unit) -&gt;
            Rpc_server.connector -&gt;
            Rpc.protocol -&gt;
            Rpc.mode -&gt;
            Unixqueue.event_system -&gt;
            Rpc_server.t
    end
end
</code></pre>
<p>There are two functions: <code class="code">P.V.create_server</code> acts as a synchronous
server, and <code class="code">P.V.create_async_server</code> works as asynchronous
server. Let's first explain the simpler synchronous case.</p>

<p><code class="code">P.V.create_server</code> accepts a number of labeled arguments and a number
of anonymous arguments. There is always an optional <code class="code">limit</code> parameter
limiting the number of pending connections accepted by the server
(default: 20); this is the second parameter of the <code class="code">Unix.listen</code>
system call. For every procedure p realized by the server there is a
labeled argument <code class="code">proc_</code>p passing the function actually computing the
procedure. For synchronous servers, this function simply gets the
argument of the procedure and must return the result of the
procedure. In this example, we only want to realize the <code class="code">add</code>
procedure, and so there is only a <code class="code">proc_add</code> argument. The anonymous
<a href="Rpc_server.html#TYPEconnector"><code class="code">Rpc_server.connector</code></a> argument specifies the internet port (or the
file descriptor) on which the server will listen for incoming
connections. The <a href="Rpc.html#TYPEprotocol"><code class="code">Rpc.protocol</code></a> argument defines whether this is a
TCP-like (stream-oriented) or a UDP-like (datagram-oriented)
service. The <a href="Rpc.html#TYPEmode"><code class="code">Rpc.mode</code></a> parameter selects how the connector must be
handled: Whether it acts like a socket or whether is behaves like an
already existing bidirectional pipeline. Finally, the function expects
the event system to be passed as last argument.</p>

<p>For example, to define a server accepting connections on the local
loopback interface on TCP port 6789, the following statement creates
such a server:</p>

<pre class="codepre"><code class="code">let esys = Unixqueue.create_event_system in
let server = 
  Calculate_srv.P.V.create_server
    ~proc_add: add
    (Rpc_server.Localhost 6789)            (* connector *)
    Rpc.Tcp                                (* protocol *)
    Rpc.Socket                             (* mode *)
    esys
</code></pre>
<p>Note that this statement creates the server, but actually does not
serve the incoming connections. You need an additionally</p>

<pre class="codepre"><code class="code">Unixqueue.run esys
</code></pre>
<p>to start the service. (Note: If the server raises an exception, it will
fall through to the caller of <code class="code">Unixqueue.run</code>. The recommended way of
handling this is to log the exception, and call <code class="code">Unixqueue.run</code> again
in a loop. If too many exceptions occur in very short time the program
should terminate.)</p>

<p>Not all combinations of connectors, protocols, and modes are
sensible. Especially the following values work:</p>

<ul>
<li>TCP internet servers: One of the connectors <code class="code">Localhost</code>
  or <code class="code">Portmapped</code>; the protocol <code class="code">Rpc.Tcp</code>; the mode <code class="code">Rpc.Socket</code></li>
<li>UDP internet servers: One of the connectors <code class="code">Localhost</code>
  or <code class="code">Portmapped</code>; the protocol <code class="code">Rpc.Udp</code>; the mode <code class="code">Rpc.Socket</code></li>
<li>Stream-based Unix domain socket servers: The
  connector <code class="code">Unix</code>, the protocol <code class="code">Rpc.Tcp</code>; the mode <code class="code">Rpc.Socket</code></li>
<li>Datagram-based Unix domain socket servers: These are
  not supported</li>
<li>Serving an already accepted (inetd) stream connection:
  The connector <code class="code">Descriptor</code>; the protocol <code class="code">Rpc.Tcp</code>; the mode <code class="code">Rpc.BiPipe</code></li>
</ul>
<p>The connector <code class="code">Portmapped</code> registers the service at the local
portmapper, and is the connector of choice.</p>

<p>Note that servers with mode=<code class="code">Socket</code> never terminate; they wait
forever for service requests. On the contrary, servers with
mode=<code class="code">BiPipe</code> process only the current (next) request, and terminate
then.</p>

<p>The resulting server is synchronous because the next request is only
accepted after the previous request has been finished. This means that
the calls are processed in a strictly serialized way (one after
another); however, the network traffic caused by the current and by
previous calls can overlap (to maximize network performance).</p>

<p>In contrast to this, an asynchronous server needs not respond
immediately to an RPC call. Once the call has been registered, the
server is free to reply whenever it likes to, even after other calls
have been received.  For example, you can synchronize several clients:
Only after both clients A and B have called the procedure <code class="code">sync</code>, the
replies of the procedures are sent back:</p>

<pre class="codepre"><code class="code">let client_a_sync = ref None
let client_b_sync = ref None

let sync s arg send_result =
  if arg.name_of_client = "A" then
    client_a_sync := Some send_result;
  if arg.name_of_client = "B" then
    client_b_sync := Some send_result;
  if !client_a_sync &lt;&gt; None &amp;&amp; !client_b_sync &lt;&gt; None then (
    let Some send_result_to_a = !client_a_sync in
    let Some send_result_to_b = !client_b_sync in
    send_result_to_a "Synchronized";
    send_result_to_b "Synchronized";
  )

let server =
  Sync.V.create_async_server
    ~proc_sync: sync
    ...
</code></pre>
<p>Here, the variables <code class="code">client_a_sync</code> and <code class="code">client_b_sync</code> store whether
one of the clients have already called the <code class="code">sync</code> service, and if so,
the variables store also the function that needs to be called to pass
the result back. For example, if <code class="code">A</code> calls <code class="code">sync</code> first, it is only
recorded that there was such a call; because send_result is not
invoked, <code class="code">A</code> will not get a reply. However, the function <code class="code">send_result</code>
is stored in <code class="code">client_a_sync</code> such that it can be invoked later. If <code class="code">B</code>
calls the <code class="code">sync</code> procedure next, <code class="code">client_b_sync</code> is updated, too.
Because now both clients have called the service, synchronization has
happed, and the answers to the procedure calls can be sent back to the
clients. This is done by invoking the functions that have been
remembered in <code class="code">client_a_sync</code> and <code class="code">client_b_sync</code>; the arguments of
these functions are the return values of the <code class="code">sync</code> procedure.</p>

<p>It is even possible for an asynchronous server not to respond at all;
for example to implement batching (the server receives a large number
of calls on a TCP connection and replies only to the last call; the
reply to the last call implicitly commits that all previous calls have
been received, too).</p>

<p>To create multi-port servers, several servers can share the same event
system; e.g.</p>

<pre class="codepre"><code class="code">let esys = Unixqueue.create_event_system in
let tcp_server = 
  P.V.create_server ... Rpc.Tcp ... esys in
let udp_server = 
  P.V.create_server ... Rpc.Udp ... esys in
Unixqueue.run esys
</code></pre>
<p>(Note: To create servers that implement several program or version
definitions, look for what the -srv2 switch of <code class="code">ocamlrpcgen</code> generated.)</p>

<h3 id="debuggig">Debugging aids</h3>
<p>There are some built-in debugging aids for developing RPC clients and
servers. Debug messages can be enabled by setting certain variables
to <code class="code">true</code>:</p>
<ul>
<li><a href="Rpc_client.Debug.html#VALenable"><code class="code">Rpc_client.Debug.enable</code></a>: Enables a general debug log for clients</li>
<li><a href="Rpc_client.Debug.html#VALenable_ptrace"><code class="code">Rpc_client.Debug.enable_ptrace</code></a>: Enables the client-side procedure
    trace. For every procedure call two messages are emitted, one for
    the request message and one for the response message. The level of
    verbosity can be set with <a href="Rpc_client.Debug.html#VALptrace_verbosity"><code class="code">Rpc_client.Debug.ptrace_verbosity</code></a>.</li>
<li><a href="Rpc_server.Debug.html#VALenable"><code class="code">Rpc_server.Debug.enable</code></a>: Enables a general debug log for servers</li>
<li><a href="Rpc_server.Debug.html#VALenable_ptrace"><code class="code">Rpc_server.Debug.enable_ptrace</code></a>: Enables the server-side procedure
    trace. For every procedure call three messages are emitted, one for
    the request message, one at the time the request is decoded, and one
    for the response message. The level of
    verbosity can be set with <a href="Rpc_server.Debug.html#VALptrace_verbosity"><code class="code">Rpc_server.Debug.ptrace_verbosity</code></a>.</li>
<li><a href="Rpc_server.Debug.html#VALenable_ctrace"><code class="code">Rpc_server.Debug.enable_ctrace</code></a>: Enables the server-side connection
    trace</li>
</ul>
<p>The messages are output via <a href="Netlog.Debug.html"><code class="code">Netlog.Debug</code></a>, and have a <code class="code">`Debug</code> log
level.</p>

<p>In Netplex context, the messages are redirected to the current Netplex
logger, so that they appear in the normal log file. Also, messages are
suppressed when they refer to the internally used RPC clients and servers.</p>

<h2 id="rpcgen">Command line arguments of ocamlrpcgen</h2>
<p>The tool accepts the following options:</p>

<pre class="codepre"><code class="code">usage: ocamlrpcgen [-aux] [-clnt] [-srv] [-srv2]
                   [-int   (abstract | int32 | unboxed) ]
                   [-hyper (abstract | int64 | unboxed) ]  
                   [-cpp   (/path/to/cpp | none) ]
                   [-D var=value]
                   [-U var]
                   [-direct]
                   file.xdr ...
</code></pre>
<ul>
<li><code class="code">-aux</code>: Creates for every XDR file the auxiliary
   module containing the type and constant definitions as O'Caml expressions, and
   containing the conversion functions implementing the language mapping.</li>
<li><code class="code">-clnt</code>: Creates for every XDR file a client module.</li>
<li><code class="code">-srv</code>: Creates for every XDR file a server module.</li>
<li><code class="code">-srv2</code>: Creates for every XDR file a new-style server module.</li>
<li><code class="code">-int abstract</code>: Uses <a href="Netnumber.html#TYPEint4"><code class="code">Netnumber.int4</code></a> for signed ints and
  <a href="Netnumber.html#TYPEuint4"><code class="code">Netnumber.uint4</code></a> for unsigned ints as default integer representation.
  This is the default. </li>
<li><code class="code">-int int32</code>: Uses <code class="code">int32</code> for both signed and unsigned
  ints as default integer representation. Note that overflows are ignored for
  unsigned ints; i.e. large unsigned XDR integers are mapped to negative <code class="code">int32</code>
  values.</li>
<li><code class="code">-int unboxed</code>: Uses <code class="code">Pervasives.int</code> for both signed and
  unsigned ints as default integer representation. XDR values outside the range
  of O'Camls 31 bit signed ints are rejected (raise an exception).</li>
<li><code class="code">-hyper abstract</code>: Uses <a href="Netnumber.html#TYPEint8"><code class="code">Netnumber.int8</code></a> for signed ints and
  <a href="Netnumber.html#TYPEuint8"><code class="code">Netnumber.uint8</code></a> for unsigned ints as default hyper (64 bit integer) 
  representation. This is the default.</li>
<li><code class="code">-hyper int64</code>: Uses <code class="code">int64</code> for both signed and unsigned
  ints as default hyper representation. Note that overflows are ignored for
  unsigned ints; i.e. large unsigned XDR hypers are mapped to negative <code class="code">int64</code>
  values.</li>
<li><code class="code">-hyper unboxed</code>: Uses <code class="code">Pervasives.int</code> for both signed and
  unsigned ints as default hyper representation. XDR values outside the range
  of O'Camls 31 bit signed ints are rejected (raise an exception).</li>
<li><code class="code">-cpp /path/to/cpp</code>: Applies the C preprocessor found
  under /path/to/cpp on the XDR files before these are processed. The default 
  is <code class="code">-cpp cpp</code> (i.e. look up the <code class="code">cpp</code> command in the command search path).</li>
<li><code class="code">-cpp none</code>: Does not call the C preprocessor.</li>
<li><code class="code">-D var=value</code>: Defines the C preprocessor variable <code class="code">var</code>
  with the given <code class="code">value</code>.</li>
<li><code class="code">-U var</code>: Undefines the C preprocessor variable <code class="code">var</code>.</li>
<li><code class="code">-direct</code>: The effect of this switch is that ocamlrpcgen generates
  different code that directly maps the XDR byte representation to
  the final OCaml values, and bypasses <a href="Netxdr.html#TYPExdr_value"><code class="code">Netxdr.xdr_value</code></a> as much as
  possible. This is the same style the traditional rpcgen preferred.
  The code is faster (up to 50% for certain large values), but also much
  longer. As a rule of thumb, this style is only a win if you have
  arrays of structs, and these structs have many elements, and there
  are not many strings (because there is no acceleration for strings).
  For example, a numerical RPC interface would definetely profit from
  this alternate code generation scheme. Except generating more code,
  there is no downside of this scheme. (Available since Ocamlnet-3.5.)</li>
</ul>
<h2 id="mapping">The language mapping underlying ocamlrpcgen</h2>
<p>The language mapping determines how the XDR types are mapped to O'Caml
types. See also <a href="Rpc_mapping_ref.html"><code class="code">Rpc_mapping_ref</code></a>.</p>

<h3 id="syn_xdr">The XDR syntax</h3>
<p>From RFC 1832:</p>

<pre class="codepre"><code class="code">      declaration:
           type-specifier identifier
         | type-specifier identifier "[" value "]"
         | type-specifier identifier "&lt;" [ value ] "&gt;"
         | "opaque" identifier "[" value "]"
         | "opaque" identifier "&lt;" [ value ] "&gt;"
         | "string" identifier "&lt;" [ value ] "&gt;"
         | type-specifier "*" identifier
         | "void"

      value:
           constant
         | identifier

      type-specifier:
           [ "unsigned" ] "int"
         | [ "unsigned" ] "hyper"
         | "float"
         | "double"
         | "quadruple"
         | "bool"
         | enum-type-spec
         | struct-type-spec
         | union-type-spec
         | identifier

      enum-type-spec:
         "enum" enum-body

      enum-body:
         "{"
            ( identifier "=" value )
            ( "," identifier "=" value )*
         "}"

      struct-type-spec:
         "struct" struct-body

      struct-body:
         "{"
            ( declaration ";" )
            ( declaration ";" )*
         "}"

      union-type-spec:
         "union" union-body

      union-body:
         "switch" "(" declaration ")" "{"
            ( "case" value ":" declaration ";" )
            ( "case" value ":" declaration ";" )*
            [ "default" ":" declaration ";" ]
         "}"

      constant-def:
         "const" identifier "=" constant ";"

      type-def:
           "typedef" declaration ";"
         | "enum" identifier enum-body ";"
         | "struct" identifier struct-body ";"
         | "union" identifier union-body ";"

      definition:
           type-def
         | constant-def

      specification:
           definition *
</code></pre>
<p><code class="code">ocamlrpcgen</code> supports a few extensions to this standard, see below.</p>

<h3 id="syn_prog">Syntax of RPC programs</h3>
<p>From RFC 1831:</p>

<pre class="codepre"><code class="code">   program-def:
      "program" identifier "{"
         version-def
         version-def *
      "}" "=" constant ";"

   version-def:
      "version" identifier "{"
          procedure-def
          procedure-def *
      "}" "=" constant ";"

   procedure-def:
      type-specifier identifier "(" type-specifier
        ("," type-specifier )* ")" "=" constant ";"

</code></pre>
<h3 id="map_names">Mapping names</h3>
<p>Because XDR has a different naming concept than O'Caml, sometimes
identifiers must be renamed. For example, if you have two structs with
equally named components</p>

<pre class="codepre"><code class="code">struct a {
  t1 c;
  ...;
}

struct b {
  t2 c;
  ...;
}
</code></pre>
<p>the corresponding O'Caml types will be</p>

<pre class="codepre"><code class="code">type a = { c : t1; ... }
type b = { c' : t2; ... }
</code></pre>
<p>i.e. the second occurrence of <code class="code">c</code> has been renamed to <code class="code">c'</code>. Note that
<code class="code">ocamlrpcgen</code> prints always a warning for such renamings that are hard
to predict.</p>

<p>Another reason to rename an identifier is that the first letter has
the wrong case. In O'Caml, the case of the first letter must be
compatible with its namespace. For example, a module name must be
uppercase. Because RPC programs are mapped to O'Caml modules, the
names of RPC programs must begin with an uppercase letter. If this is
not the case, the identifier is (quietly) renamed, too.</p>

<p>You can specify the O'Caml name of every XDR/RPC identifier manually:
Simply add after the definition of the identifier the phrase <code class="code">=&gt;
ocaml_id</code> where <code class="code">ocaml_id</code> is the preferred name for O'Caml. Example:</p>

<pre class="codepre"><code class="code">struct a {
  t1 c =&gt; a_c;
  ...;
}

struct b {
  t2 c =&gt; b_c;
  ...;
}
</code></pre>
<p>Now the generated O'Caml types are</p>

<pre class="codepre"><code class="code">type a = { a_c : t1; ... }
type b = { b_c : t2; ... }
</code></pre>
<p>This works wherever a name is defined in the XDR file.</p>

<h3 id="map_dirs">Directives for name mapping</h3>
<p>Since Ocamlnet-3.6.7, there are now also a few directives influencing the
name mapping for structs, unions, and enums:</p>

<ul>
<li><code class="code">_lowercase</code>: the XDR name is lowercased</li>
<li><code class="code">_uppercase</code>: the XDR name is uppercased</li>
<li><code class="code">_capitalize</code>: the XDR name is capitalized</li>
<li><code class="code">_prefix "p"</code>: this prefix is prepended to the XDR name</li>
</ul>
<p>It is possible to specify several directives, which are then applied one
after the other.</p>

<ul>
<li>For structs, these directives control the name mapping of the elements.
   Place the directives before the left brace, e.g.
   <pre class="codepre"><code class="code">     struct a _lowercase _prefix "a_" {
       T1 string;
       T2 float;
     };
   </code></pre>
   This would generate the record type
   <code class="code"> type a = { a_t1 : string; a_t2 : float } </code>.</li>
</ul>
<ul>
<li>For enums, these directives control the name mapping of the generated
   constants. Again, place the directives before the left brace, e.g.
   <pre class="codepre"><code class="code">     enum x _lowercase {
       ONE = 1,
       TWO = 2
     };
   </code></pre>
   The generated OCaml constants have here names <code class="code">one</code> and <code class="code">two</code>.</li>
<li>For unions, the directives control the name mapping of the discriminating
   cases (when an enum is used for that). Place the directives before the
   <code class="code">switch</code> keyword, e.g.
   <pre class="codepre"><code class="code">     union u _lowercase _capitalize switch (x discr) {
       case ONE: void;
       case TWO: double x;
     };
   </code></pre>
   This would generate the variant type <code class="code"> [`One | `Two of float] </code> in the
   Ocaml mapping.</li>
</ul>
<h3 id="map_ints">Mapping integer types</h3>
<p>XDR defines 32 bit and 64 bit integers, each in a signed and unsigned
variant. As O'Caml does only know 31 bit signed integers (type <code class="code">int</code>; the
so-called unboxed integers), 32 bit signed integers (type <code class="code">int32</code>), and 64 bit
signed integers (type <code class="code">int64</code>), it is unclear how to map the XDR integers to
O'Caml integers.</p>

<p>The module <a href="Netnumber.html"><code class="code">Netnumber</code></a> defines the opaque types <code class="code">int4</code>, <code class="code">uint4</code>, <code class="code">int8</code>,
and <code class="code">uint8</code> which exactly correspond to the XDR types. These are
useful to pass integer values through to other applications, and for
simple identification of things. However, you cannot compute directly
with the <a href="Netnumber.html"><code class="code">Netnumber</code></a> integers. Of course, <a href="Netnumber.html"><code class="code">Netnumber</code></a> also provides
conversion functions to the basic O'Caml integer types <code class="code">int</code>, <code class="code">int32</code>,
and <code class="code">int64</code>, but it would be very inconvenient to call these
conversions for every integer individually.</p>

<p>Because of this, <code class="code">ocamlrpcgen</code> has the possibility to specify the
O'Caml integer variant for every integer value (and it generates the
necessary conversion invocations automatically). The new keywords
<code class="code">_abstract</code>, <code class="code">_int32</code>, <code class="code">_int64</code>, and <code class="code">_unboxed</code> select the variant to
use:</p>

<ul>
<li><code class="code">_abstract int</code>: A signed 32 bit integer mapped to <a href="Netnumber.html#TYPEint4"><code class="code">Netnumber.int4</code></a></li>
<li><code class="code">_int32 int</code>: A signed 32 bit integer mapped to <code class="code">int32</code></li>
<li><code class="code">_int64 int</code>: A signed 32 bit integer mapped to <code class="code">int64</code></li>
<li><code class="code">_unboxed int</code>: A signed 32 bit integer mapped to <code class="code">int</code></li>
<li><code class="code">unsigned _abstract int</code>: An unsigned 32 bit integer mapped to <a href="Netnumber.html#TYPEuint4"><code class="code">Netnumber.uint4</code></a></li>
<li><code class="code">unsigned _int32 int</code>: An unsigned 32 bit integer mapped to <code class="code">int32</code> 
  (ignoring overflows)</li>
<li><code class="code">unsigned _int64 int</code>: An unsigned 32 bit integer mapped to <code class="code">int64</code></li>
<li><code class="code">unsigned _unboxed int</code>: An unsigned 32 bit integer mapped to <code class="code">int</code></li>
</ul>
<p>Note that the 32 bits of the unsigned integer are simply casted to the
32 bits of <code class="code">int32</code> in the case of <code class="code">unsigned _int32 int</code> (the meaning
of the sign is ignored). In contrast to this, the <code class="code">_unboxed</code> specifier
causes a language mapping rejecting too small or too big values.</p>

<p>A similar mapping can be specified for the 64 bit integers (hypers):</p>

<ul>
<li><code class="code">_abstract hyper</code>: A signed 64 bit integer mapped to <a href="Netnumber.html#TYPEint8"><code class="code">Netnumber.int8</code></a></li>
<li><code class="code">_int64 hyper</code>: A signed 64 bit integer mapped to <code class="code">int64</code></li>
<li><code class="code">_unboxed hyper</code>: A signed 64 bit integer mapped to <code class="code">int</code></li>
<li><code class="code">unsigned _abstract hyper</code>: An unsigned 64 bit integer mapped to <a href="Netnumber.html#TYPEuint8"><code class="code">Netnumber.uint8</code></a></li>
<li><code class="code">unsigned _int64 hyper</code>: An unsigned 64 bit integer mapped to <code class="code">int64</code></li>
<li><code class="code">unsigned _unboxed hyper</code>: An unsigned 64 bit integer mapped to <code class="code">int</code></li>
</ul>
<p>Again, <code class="code">unsigned _int64 hyper</code> causes that the 64 bits of the XDR values are
casted to <code class="code">int64</code>.</p>

<p>If the keyword specifying the kind of language mapping is omitted, the
default mapping applies. Unless changed on the command line (options
<code class="code">-int</code> and <code class="code">-hyper</code>), the default mapping is <code class="code">_abstract</code>.</p>

<h3 id="map_fps">Mapping floating-point types</h3>
<p>The XDR types <code class="code">single</code> and <code class="code">double</code> are supported and both mapped
to the O'Caml type <code class="code">float</code>. The XDR type <code class="code">quadruple</code> is not supported.</p>

<p>The code for <code class="code">double</code> assumes that the CPU represents floating-point
numbers according to the IEEE standards.</p>

<h3 id="map_strings">Mapping string and opaque types</h3>
<p>Strings and opaque values are mapped to O'Caml strings. If strings have a fixed
length or a maximum length, this constraint is checked when the conversion is
performed.</p>

<p>Since Ocamlnet-3, strings can be declared as "managed" in the XDR 
file, e.g.</p>

<pre class="codepre"><code class="code">typedef _managed string s&lt;&gt;;
</code></pre>
<p>A managed string is mapped to the object type <a href="Netxdr_mstring.mstring-c.html"><code class="code">Netxdr_mstring.mstring</code></a>.
The idea of managed strings is to avoid data copies as much as possible,
and to introduce some freedom of representation. In particular, managed
strings can be backed by normal strings or by bigarrays of char. The
RPC library chooses the representation that works best, and avoids copying
so far possible.</p>

<h3 id="map_arrays">Mapping array types</h3>
<p>Arrays are mapped to O'Caml arrays. If arrays have a fixed
length or a maximum length, this constraint is checked when the conversion is
performed.</p>

<h3 id="map_records">Mapping record types (structs)</h3>
<p>Structs are mapped to O'Caml records by default. The elements are mutable.</p>

<p>Since Ocamlnet-3.6.7 it is possible to add an equality constraint, e.g.</p>

<pre class="codepre"><code class="code">struct x _equals "MyModule.x" {
  ...
};
</code></pre>
<p>would generate</p>

<pre class="codepre"><code class="code">type x = MyModule.x = { ... }
</code></pre>
<p>Another option since 3.6.7 is to request a tuple instead of a record:</p>

<pre class="codepre"><code class="code">struct x _tuple { ... }
</code></pre>
<h3 id="map_enums">Mapping enumerated types (enums)</h3>
<p>Enumerated types are mapped to <a href="Netnumber.html#TYPEint4"><code class="code">Netnumber.int4</code></a> (always, regardless of
what the <code class="code">-int</code> option specifies). The enumerated constants are mapped
to let-bound values of the same name. Example: The XDR definition</p>

<pre class="codepre"><code class="code">enum e {
  A = 1;
  B = 2;
}
</code></pre>
<p>generates the following lines of code in the auxiliary module:</p>

<pre class="codepre"><code class="code">type e = Netnumber.int4;;
val a : Netnumber.int4;;
val b : Netnumber.int4;;
</code></pre>
<p>However, when the XDR conversion is performed, it is checked whether values of
enumerators are contained in the set of allowed values.</p>

<p>The special enumerator <code class="code">bool</code> is mapped to the O'Caml type <code class="code">bool</code>.</p>

<h3 id="map_eunions">Mapping union types discriminated by enumerations</h3>
<p>Often, XDR unions are discriminated by enumerations, so this case is
handled specially. For every case of the enumerator, a polymorphic
variant is generated that contains the selected arm of the
union. Example:</p>

<pre class="codepre"><code class="code">enum e {
  A = 1;
  B = 2;
  C = 3;
  D = 4;
}

union u (e discr) {
  case A: 
    int x;
  case B:
    hyper y;
  default:
    string z;
}
</code></pre>
<p>This is mapped to the O'Caml type definitions:</p>

<pre class="codepre"><code class="code">type e = Netnumber.int4;;
type u =
  [ `a of Netnumber.int4
  | `b of Netnumber.int8
  | `c of string
  | `d of string
  ]
</code></pre>
<p>Note that the identifiers of the components (<code class="code">discr</code>, <code class="code">x</code>, <code class="code">y</code>, <code class="code">z</code>)
have vanished; they are simply not necessary in a sound typing
environment. Also note that the default case has been expanded;
because the cases of the enumerator are known it is possible to
determine the missing cases meant by <code class="code">default</code> and to define these
cases explicitly.</p>

<h3 id="map_iunions">Mapping union types discriminated by integers</h3>
<p>If the discriminant has integer type, a different mapping scheme is
used. For every case occuring in the union definition a separate
polymorphic variant is defined; if necessary, an extra default variant
is added. Example:</p>

<pre class="codepre"><code class="code">union u (int discr) {
  case -1: 
    int x;
  case 1:
    hyper y;
  default:
    string z;
}
</code></pre>
<p>This is mapped to the O'Caml type definition:</p>

<pre class="codepre"><code class="code">type u = 
  [ `__1 of Netnumber.int4
  | `_1  of Netnumber.int8
  | `default of (Netnumber.int4 * string)
  ]
</code></pre>
<p>Note that positive cases get variant tags of the form "_n" and that
negative cases get variant tags of the form "__n". The default case is
mapped to the tag <code class="code">`default</code> with two arguments: First the value of
the discriminant, second the value of the default component.</p>

<p>This type of mapping is not recommended, and only provided for
completeness.</p>

<h3 id="map_opts">Mapping option types (*)</h3>
<p>The XDR <code class="code">*</code> type is mapped to the O'Caml <code class="code">option</code> type. Example:</p>

<pre class="codepre"><code class="code">typedef string *s;
</code></pre>
<p>is mapped to</p>

<pre class="codepre"><code class="code">type s = string option
</code></pre>
<h3 id="map_recs">Mapping recursive types</h3>
<p>Recursive types are fully supported. Unlike in the C language, you can
recursively refer to types defined before or after the current type
definition. Example:</p>

<pre class="codepre"><code class="code">typedef intlistbody *intlist;   /* Forward reference */
typedef struct {
  int value;
  intlist next;
} intlistbody;
</code></pre>
<p>This is mapped to:</p>

<pre class="codepre"><code class="code">type intlist = intlistbody option
and intlistbody = 
  { value : Netnumber.int4;
    next : intlist;
  }
</code></pre>
<p>However, it is not checked whether there is a finite fixpoint of the
recursion. The O'Caml compiler will do this check anyway, so it not
really needed within <code class="code">ocamlrpcgen</code>.</p>

<h2 id="lib">Overview over the RPC library</h2>
<p>Normally, only the following modules are of interest:</p>

<ul>
<li><a href="Netnumber.html"><code class="code">Netnumber</code></a>: Supports serialization/deserialization of the
  basic integer and fp types</li>
<li><a href="Rpc.html"><code class="code">Rpc</code></a>: Contains some types needed everyhwere</li>
<li><a href="Rpc_client.html"><code class="code">Rpc_client</code></a>: Contains the functions supporting RPC clients</li>
<li><a href="Rpc_server.html"><code class="code">Rpc_server</code></a>: Contains the functions supporting RPC servers</li>
<li><a href="Rpc_portmapper.html"><code class="code">Rpc_portmapper</code></a>: Functions to contact the portmapper service</li>
<li><a href="Rpc_auth_sys.html"><code class="code">Rpc_auth_sys</code></a>: AUTH_SYS style authentication.</li>
</ul>
<h2 id="rpc_netplex">Netplex RPC systems</h2>
<p>If you need multi-processing for your RPC program, the Netplex library
might be a good solution (see <a href="Netplex_intro.html"><code class="code">Netplex_intro</code></a>). It is limited to
stream connections (TCP), however. With Netplex it is possible to
develop systems of RPC services that connect to each other to do a
certain job. Effectively, Netplex supports a component-based approach
comparable to Corba, DCOM or Java Beans, but much more lightweight and
efficient. In the following we call our technology <b>Netplex RPC
systems</b>.</p>

<p>In this section it is assumed that you are familiar with the Netplex
concepts (see <a href="Netplex_intro.html"><code class="code">Netplex_intro</code></a> for an introduction).</p>

<p>The module <a href="Rpc_netplex.html"><code class="code">Rpc_netplex</code></a> (part of the <code class="code">netplex</code> findlib library)
allows us to encapsulate RPC servers as Netplex services. For instance,
to turn the <code class="code">calculate.x</code> example of above into a service we can do</p>

<pre class="codepre"><code class="code">let factory =
  Rpc_netplex.rpc_factory
    ~name:"Calculate"
    ~configure:(fun _ _ -&gt; ())
    ~setup:(fun srv () -&gt;
             Calculate_srv.bind
	        ~proc_add: add
                srv
           )
    ()
</code></pre>
<p>and pass this <code class="code">factory</code> to <a href="Netplex_main.html#VALstartup"><code class="code">Netplex_main.startup</code></a>. Note that we have
to generate <code class="code">calculate_srv.ml</code> with the <code class="code">-srv2</code> switch of
<code class="code">ocamlrpcgen</code>, otherwise <code class="code">Calculate_srv.bind</code> is not available.</p>

<p>In the netplex config file we can refer to (and enable) this service
by a section like</p>

<pre class="codepre"><code class="code">    service {
        name = "Calculate_service"            (* An arbitrary service name *)
        protocol {
	    name = "Calculate_proto"          (* An arbitrary protocol name *)
            address {
	        type = "internet";
                bind = "0.0.0.0:2123"
            }
        };
        processor {
            type = "Calculate"                (* The ~name from above *)
        };
        workload_manager {
            type = "constant";
            threads = 1;                      (* Run in 1 process/thread *)
        };
    }
</code></pre>
<p>The interesting points of this technology are:</p>

<ul>
<li>You can bundle several services into one program. The services can be
  RPC-implemented or by using other protocol modules that are compatible
  with Netplex like the <a href="Nethttpd_plex.html"><code class="code">Nethttpd_plex</code></a> web server.</li>
<li>You can profit from multi-processing or multi-threading.</li>
<li>Netplex provides a framework for logging, a message bus, and start/stop.</li>
</ul>
<p>Currently, there is no directory service where one can register 
services by name and look them up. Such a service is under development,
however, and will be released once the major functions work.</p>

<h2 id="restrictions">Restrictions of the current implementation</h2>
<p>The authentication styles AUTH_DH and AUTH_LOCAL are not yet supported
on all platforms.</p>

<p>The implementation uses an intermediate, symbolic representation of
the values to transport over the network. This may restrict the
performance.</p>

<p>Quadruple-precision fp numbers are not supported.</p>

<p>RPC broadcasts are not supported.</p>

<p>TI-RPC and rpcbind versions 3 and 4 are not supported. (Note: There
is some restricted support to contact existing TI-RPC servers over
local transport in the <code class="code">Rpc_xti</code> module.)</p>
</div>
</body></html>