aboutsummaryrefslogblamecommitdiffstats
path: root/main/lua-socket/git.patch
blob: d665fc2323d06793775246236387e353fd8e8f43 (plain) (tree)
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
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609









































































































                                                                                










                                                  






















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































                                                                                                                                                                                                                                          



























































                                                                              












































                                                                                                                                                                                                                                
                                
                             













                                                           
                                                

































                                              




























































































                                                                                                   
                                        
                             

                  




























                                                                                    









                                                       









                                                                    







                                                                      
                                                                          





                                                         
                                                     
                                
                                                    

                                                              




























                                                                              







                                                                      



























































                                                                              
                                        
                             

                  




                     




                                                
                                                         








                                                                              



































































                                                                              

  



                                                                


                                                                          


                                 
                                  


                                 









                                             
                                      
                

                                           

                                                                                  








                                           

  






















































                                                                              
                                      
                             

                 
                                                                






                                                         






















                                                             
                                        
                             

                  
                                          



                                                                              

                                       
                
                                    



















                                                                              







                                                                          
                                                  







                                              
                         










                                                         





































































































                                                                                






                                    
                             

                































































                                                                                





                                                                      




























































































































































































































































































































                                                                                                  
                                          
                             

                   



























                                                                              









                                                 
                                             















                                               
                             

                     

                                                                              

                     
 

                    

                                                                              
                                            







                                                                              
                                                            













                                                                              











                                                                           
                                        
                             

                  
                               











                                                                               









                                                






                               
                                              




                                
                                                 











                                                  










































                                                                             







                                                                    





                                                        







                                                                    
                                            






                               
                                   










                                                                  















                                                                  


             


                                                                               






                                                                   

















                                                                                    
 











                                            









                                        


















                                                







                                               
                                   









                                     






























                                                               
                                    
                             

                












                                                                                             







                                                                           













                                                                              


















                                                                              
                                                            







                                   
                                                            










                                                                              
                                                      












                                                                              
                                                                         







                                                      
                                                                           












                                                                              
                                                                      







                                                          
                                                                        












                                                                              
                                                                         







                                                                    
                                                                         







                                                                              
                                                            







                                                                        
                                                            










                                                              
                                                            







                                                           
                                                              







                                                                        
                                                              










                                                              
                                                              







                                                           
                                                              







                                                                              
                                                           







                                                  
                                                                  










                                                                              
                                                                        







                                                                              
                                                                                    









                                                                              
                                                           







                                                                        
                                                           







                                                                  
                                                           







                                                                              
                                                                                               









                                                                
                                                                                               







                                                                             
                                                                                                 

















                                                                              
                                                               















                                                              
                                                             











                                                                              
                                                              







                                                                       
                                                                












                                                     
                                                              







                                                                              
                                                                                

















                                                                              
                                                              























                                                                              
                                                            







                                               




















































































































































































                                                                                                      
                                          
                             

                   






















                                                                              









































                                                                              














































































































































































































































































































































































































































































































































































































































































































































































































































































































































































                                                                                          
                                                                              


                      
                                                                              











































































































































































                                                                                     
                                          
                             





























































































































                                                                                                   









                                                                                  















                                                                              







                                                                                                    









                                                                             
                                                                                                    







                                                                              
                                                                                           









                                                                             
                                                                                           







                                                                              









                                                                                                    









                                                                             
                                                             







                                                                                 
                                                                                     







                                                        
                                                                









                                                          
                                       






                                                   


                                  

      
 










































                                                                            
                             

                   






                                                                              






                                         















































































































































































































                                                                                                  



                                                         
                                         
                                                           
                                        

      
 




























                                                                      
                                                             









                                                                                      
                                                                                                       



















                                                                                 



                                                                            





                                                                                
                                                                                     


                                                                                

  
                                          

                                






























                                                                            

                                                  
       

                                           
















                                                                 






































                                                                                           





















































































































































                                                                               





















































































































































































































































































































































































































                                                                                                                                   
diff --git a/doc/http.html b/doc/http.html
index cd41c0d..3b7a8b1 100644
--- a/doc/http.html
+++ b/doc/http.html
@@ -112,12 +112,15 @@ the HTTP module:
 </p>
 
 <ul>
-<li> <tt>PORT</tt>: default port used for connections; 
-<li> <tt>PROXY</tt>: default proxy used for connections; 
+<li> <tt>PROXY</tt>: default proxy used for connections;
 <li> <tt>TIMEOUT</tt>: sets the timeout for all I/O operations;
 <li> <tt>USERAGENT</tt>: default user agent reported to server.
 </ul>
 
+<p class=note id="post">
+Note: These constants are global. Changing them will also
+change the behavior other code that might be using LuaSocket.
+</p>
 
 <!-- http.request ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
diff --git a/doc/mime.html b/doc/mime.html
index ae136fd..8cb3507 100644
--- a/doc/mime.html
+++ b/doc/mime.html
@@ -72,34 +72,6 @@ local mime = require("mime")
 
 <h3 id=high>High-level filters</h3>
 
-<!-- normalize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class=name id="normalize">
-mime.<b>normalize(</b>[marker]<b>)</b>
-</p>
-
-<p class=description>
-Converts most common end-of-line markers to a specific given marker. 
-</p>
-
-<p class=parameters>
-<tt>Marker</tt> is the new marker. It defaults to CRLF, the canonic 
-end-of-line marker defined by the MIME standard.
-</p>
-
-<p class=return>
-The function returns a filter that performs the conversion. 
-</p>
-
-<p class=note>
-Note: There is no perfect solution to this problem. Different end-of-line
-markers are an evil that will probably plague developers forever. 
-This function, however, will work perfectly for text created with any of
-the most common end-of-line markers, i.e. the Mac OS (CR), the Unix (LF), 
-or the DOS (CRLF) conventions. Even if the data has mixed end-of-line
-markers, the function will still work well, although it doesn't 
-guarantee that the number of empty lines will be correct.
-</p>
 
 <!-- decode +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
@@ -159,6 +131,35 @@ base64 = ltn12.filter.chain(
 )
 </pre>
 
+<!-- normalize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="normalize">
+mime.<b>normalize(</b>[marker]<b>)</b>
+</p>
+
+<p class=description>
+Converts most common end-of-line markers to a specific given marker. 
+</p>
+
+<p class=parameters>
+<tt>Marker</tt> is the new marker. It defaults to CRLF, the canonic 
+end-of-line marker defined by the MIME standard.
+</p>
+
+<p class=return>
+The function returns a filter that performs the conversion. 
+</p>
+
+<p class=note>
+Note: There is no perfect solution to this problem. Different end-of-line
+markers are an evil that will probably plague developers forever. 
+This function, however, will work perfectly for text created with any of
+the most common end-of-line markers, i.e. the Mac OS (CR), the Unix (LF), 
+or the DOS (CRLF) conventions. Even if the data has mixed end-of-line
+markers, the function will still work well, although it doesn't 
+guarantee that the number of empty lines will be correct.
+</p>
+
 <!-- stuff +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class=name id="stuff">
@@ -466,7 +467,7 @@ marker.
 <p>
 <small>
 Last modified by Diego Nehab on <br>
-Thu Apr 20 00:25:44 EDT 2006
+Fri Mar  4 15:19:17 BRT 2016
 </small>
 </p>
 </center>
diff --git a/doc/reference.css b/doc/reference.css
index b1dd25d..04e38cf 100644
--- a/doc/reference.css
+++ b/doc/reference.css
@@ -2,6 +2,7 @@ body {
     margin-left: 1em; 
     margin-right: 1em; 
     font-family: "Verdana", sans-serif; 
+    background: #ffffff;
 }
 
 tt {
diff --git a/doc/reference.html b/doc/reference.html
index e9bb5eb..287dc19 100644
--- a/doc/reference.html
+++ b/doc/reference.html
@@ -147,6 +147,7 @@ Support, Manual">
 <a href="socket.html#connect">connect</a>,
 <a href="socket.html#connect">connect4</a>,
 <a href="socket.html#connect">connect6</a>,
+<a href="socket.html#datagramsize">_DATAGRAMSIZE</a>,
 <a href="socket.html#debug">_DEBUG</a>,
 <a href="dns.html#dns">dns</a>,
 <a href="socket.html#gettime">gettime</a>,
@@ -158,11 +159,14 @@ Support, Manual">
 <a href="socket.html#skip">skip</a>,
 <a href="socket.html#sleep">sleep</a>,
 <a href="socket.html#setsize">_SETSIZE</a>,
+<a href="socket.html#socketinvalid">_SOCKETINVALID</a>,
 <a href="socket.html#source">source</a>,
 <a href="tcp.html#socket.tcp">tcp</a>,
+<a href="tcp.html#socket.tcp4">tcp4</a>,
 <a href="tcp.html#socket.tcp6">tcp6</a>,
 <a href="socket.html#try">try</a>,
 <a href="udp.html#socket.udp">udp</a>,
+<a href="udp.html#socket.udp4">udp4</a>,
 <a href="udp.html#socket.udp6">udp6</a>,
 <a href="socket.html#version">_VERSION</a>.
 </blockquote>
@@ -183,6 +187,7 @@ Support, Manual">
 <a href="tcp.html#getpeername">getpeername</a>,
 <a href="tcp.html#getsockname">getsockname</a>,
 <a href="tcp.html#getstats">getstats</a>,
+<a href="tcp.html#gettimeout">gettimeout</a>,
 <a href="tcp.html#listen">listen</a>,
 <a href="tcp.html#receive">receive</a>,
 <a href="tcp.html#send">send</a>,
@@ -203,6 +208,7 @@ Support, Manual">
 <a href="udp.html#getoption">getoption</a>,
 <a href="udp.html#getpeername">getpeername</a>,
 <a href="udp.html#getsockname">getsockname</a>,
+<a href="udp.html#gettimeout">gettimeout</a>,
 <a href="udp.html#receive">receive</a>,
 <a href="udp.html#receivefrom">receivefrom</a>,
 <a href="udp.html#send">send</a>,
diff --git a/doc/smtp.html b/doc/smtp.html
index bbbff80..600ec37 100644
--- a/doc/smtp.html
+++ b/doc/smtp.html
@@ -114,6 +114,124 @@ the SMTP module:
 <li> <tt>ZONE</tt>: default time zone.
 </ul>
 
+<!-- message ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id=message> 
+smtp.<b>message(</b>mesgt<b>)</b>
+</p>
+
+<p class=description>
+Returns a <em>simple</em>
+<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> source that sends an SMTP message body, possibly multipart (arbitrarily deep). 
+</p>
+
+<p class=parameters>
+The only parameter of the function is a table describing the message.
+<tt>Mesgt</tt> has the following form (notice the recursive structure):
+</p>
+
+<blockquote>
+<table summary="Mesgt table structure">
+<tr><td><tt>
+mesgt = {<br>
+&nbsp;&nbsp;headers = <i>header-table</i>,<br>
+&nbsp;&nbsp;body = <i>LTN12 source</i> or <i>string</i> or 
+<i>multipart-mesgt</i><br>
+}<br>
+&nbsp;<br>
+multipart-mesgt = {<br>
+&nbsp;&nbsp;[preamble = <i>string</i>,]<br>
+&nbsp;&nbsp;[1] = <i>mesgt</i>,<br>
+&nbsp;&nbsp;[2] = <i>mesgt</i>,<br>
+&nbsp;&nbsp;...<br>
+&nbsp;&nbsp;[<i>n</i>] = <i>mesgt</i>,<br>
+&nbsp;&nbsp;[epilogue = <i>string</i>,]<br>
+}<br>
+</tt></td></tr>
+</table>
+</blockquote>
+
+<p class=parameters>
+For a simple message, all that is needed is a set of <tt>headers</tt>
+and the <tt>body</tt>. The message <tt>body</tt> can be given as a string
+or as a <em>simple</em> 
+<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> 
+source. For multipart messages, the body is a table that
+recursively defines each part as an independent message, plus an optional
+<tt>preamble</tt> and <tt>epilogue</tt>.
+</p>
+
+<p class=return> 
+The function returns a <em>simple</em> 
+<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> 
+source that produces the
+message contents as defined by <tt>mesgt</tt>, chunk by chunk. 
+Hopefully, the following
+example will make things clear. When in doubt, refer to the appropriate RFC
+as listed in the introduction.  </p>
+
+<pre class=example>
+-- load the smtp support and its friends
+local smtp = require("socket.smtp")
+local mime = require("mime")
+local ltn12 = require("ltn12")
+
+-- creates a source to send a message with two parts. The first part is 
+-- plain text, the second part is a PNG image, encoded as base64.
+source = smtp.message{
+  headers = {
+     -- Remember that headers are *ignored* by smtp.send. 
+     from = "Sicrano de Oliveira &lt;sicrano@example.com&gt;",
+     to = "Fulano da Silva &lt;fulano@example.com&gt;",
+     subject = "Here is a message with attachments"
+  },
+  body = {
+    preamble = "If your client doesn't understand attachments, \r\n" ..
+               "it will still display the preamble and the epilogue.\r\n" ..
+               "Preamble will probably appear even in a MIME enabled client.",
+    -- first part: no headers means plain text, us-ascii.
+    -- The mime.eol low-level filter normalizes end-of-line markers.
+    [1] = { 
+      body = mime.eol(0, [[
+        Lines in a message body should always end with CRLF. 
+        The smtp module will *NOT* perform translation. However, the 
+        send function *DOES* perform SMTP stuffing, whereas the message
+        function does *NOT*.
+      ]])
+    },
+    -- second part: headers describe content to be a png image, 
+    -- sent under the base64 transfer content encoding.
+    -- notice that nothing happens until the message is actually sent. 
+    -- small chunks are loaded into memory right before transmission and 
+    -- translation happens on the fly.
+    [2] = { 
+      headers = {
+        ["content-type"] = 'image/png; name="image.png"',
+        ["content-disposition"] = 'attachment; filename="image.png"',
+        ["content-description"] = 'a beautiful image',
+        ["content-transfer-encoding"] = "BASE64"
+      },
+      body = ltn12.source.chain(
+        ltn12.source.file(io.open("image.png", "rb")),
+        ltn12.filter.chain(
+          mime.encode("base64"),
+          mime.wrap()
+        )
+      )
+    },
+    epilogue = "This might also show up, but after the attachments"
+  }
+}
+
+-- finally send it
+r, e = smtp.send{
+    from = "&lt;sicrano@example.com&gt;",
+    rcpt = "&lt;fulano@example.com&gt;",
+    source = source,
+}
+</pre>
+
+
 <!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class=name id=send> 
@@ -275,123 +393,6 @@ r, e = smtp.send{
 }
 </pre>
 
-<!-- message ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class=name id=message> 
-smtp.<b>message(</b>mesgt<b>)</b>
-</p>
-
-<p class=description>
-Returns a <em>simple</em>
-<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> source that sends an SMTP message body, possibly multipart (arbitrarily deep). 
-</p>
-
-<p class=parameters>
-The only parameter of the function is a table describing the message.
-<tt>Mesgt</tt> has the following form (notice the recursive structure):
-</p>
-
-<blockquote>
-<table summary="Mesgt table structure">
-<tr><td><tt>
-mesgt = {<br>
-&nbsp;&nbsp;headers = <i>header-table</i>,<br>
-&nbsp;&nbsp;body = <i>LTN12 source</i> or <i>string</i> or 
-<i>multipart-mesgt</i><br>
-}<br>
-&nbsp;<br>
-multipart-mesgt = {<br>
-&nbsp;&nbsp;[preamble = <i>string</i>,]<br>
-&nbsp;&nbsp;[1] = <i>mesgt</i>,<br>
-&nbsp;&nbsp;[2] = <i>mesgt</i>,<br>
-&nbsp;&nbsp;...<br>
-&nbsp;&nbsp;[<i>n</i>] = <i>mesgt</i>,<br>
-&nbsp;&nbsp;[epilogue = <i>string</i>,]<br>
-}<br>
-</tt></td></tr>
-</table>
-</blockquote>
-
-<p class=parameters>
-For a simple message, all that is needed is a set of <tt>headers</tt>
-and the <tt>body</tt>. The message <tt>body</tt> can be given as a string
-or as a <em>simple</em> 
-<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> 
-source. For multipart messages, the body is a table that
-recursively defines each part as an independent message, plus an optional
-<tt>preamble</tt> and <tt>epilogue</tt>.
-</p>
-
-<p class=return> 
-The function returns a <em>simple</em> 
-<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> 
-source that produces the
-message contents as defined by <tt>mesgt</tt>, chunk by chunk. 
-Hopefully, the following
-example will make things clear. When in doubt, refer to the appropriate RFC
-as listed in the introduction.  </p>
-
-<pre class=example>
--- load the smtp support and its friends
-local smtp = require("socket.smtp")
-local mime = require("mime")
-local ltn12 = require("ltn12")
-
--- creates a source to send a message with two parts. The first part is 
--- plain text, the second part is a PNG image, encoded as base64.
-source = smtp.message{
-  headers = {
-     -- Remember that headers are *ignored* by smtp.send. 
-     from = "Sicrano de Oliveira &lt;sicrano@example.com&gt;",
-     to = "Fulano da Silva &lt;fulano@example.com&gt;",
-     subject = "Here is a message with attachments"
-  },
-  body = {
-    preamble = "If your client doesn't understand attachments, \r\n" ..
-               "it will still display the preamble and the epilogue.\r\n" ..
-               "Preamble will probably appear even in a MIME enabled client.",
-    -- first part: no headers means plain text, us-ascii.
-    -- The mime.eol low-level filter normalizes end-of-line markers.
-    [1] = { 
-      body = mime.eol(0, [[
-        Lines in a message body should always end with CRLF. 
-        The smtp module will *NOT* perform translation. However, the 
-        send function *DOES* perform SMTP stuffing, whereas the message
-        function does *NOT*.
-      ]])
-    },
-    -- second part: headers describe content to be a png image, 
-    -- sent under the base64 transfer content encoding.
-    -- notice that nothing happens until the message is actually sent. 
-    -- small chunks are loaded into memory right before transmission and 
-    -- translation happens on the fly.
-    [2] = { 
-      headers = {
-        ["content-type"] = 'image/png; name="image.png"',
-        ["content-disposition"] = 'attachment; filename="image.png"',
-        ["content-description"] = 'a beautiful image',
-        ["content-transfer-encoding"] = "BASE64"
-      },
-      body = ltn12.source.chain(
-        ltn12.source.file(io.open("image.png", "rb")),
-        ltn12.filter.chain(
-          mime.encode("base64"),
-          mime.wrap()
-        )
-      )
-    },
-    epilogue = "This might also show up, but after the attachments"
-  }
-}
-
--- finally send it
-r, e = smtp.send{
-    from = "&lt;sicrano@example.com&gt;",
-    rcpt = "&lt;fulano@example.com&gt;",
-    source = source,
-}
-</pre>
-
 <!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <div class=footer>
diff --git a/doc/socket.html b/doc/socket.html
index b9303cb..35f8391 100644
--- a/doc/socket.html
+++ b/doc/socket.html
@@ -51,6 +51,30 @@ To obtain the <tt>socket</tt> namespace, run:
 local socket = require("socket")
 </pre>
 
+<!-- headers.canonic ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="headers.canonic">
+socket.headers.<b>canonic</b></p>
+
+<p> The <tt>socket.headers.canonic</tt> table 
+is used by the HTTP and SMTP modules to translate from 
+lowercase field names back into their canonic 
+capitalization. When a lowercase field name exists as a key
+in this table, the associated value is substituted in
+whenever the field name is sent out.
+</p>
+
+<p> 
+You can obtain the <tt>headers</tt> namespace if case run-time
+modifications are required by running:
+</p>
+
+<pre class=example>
+-- loads the headers module 
+local headers = require("headers")
+</pre>
+
+
 <!-- bind ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class=name id=bind> 
@@ -90,7 +114,7 @@ of connect are defined as simple helper functions that restrict the
 
 <!-- debug ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<p class=name id=debug> 
+<p class=name id=debug>
 socket.<b>_DEBUG</b>
 </p>
 
@@ -99,6 +123,19 @@ This constant is set to <tt><b>true</b></tt> if the library was compiled
 with debug support.
 </p>
 
+<!-- datagramsize +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id=debug>
+socket.<b>_DATAGRAMSIZE</b>
+</p>
+
+<p class=description>
+Default datagram size used by calls to
+<a href="udp.html#receive"<tt>receive</tt></a> and
+<a href="udp.html#receivefrom"><tt>receivefrom</tt></a>.
+(Unless changed in compile time, the value is 8192.)
+</p>
+
 <!-- get time +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class=name id=gettime> 
@@ -106,8 +143,7 @@ socket.<b>gettime()</b>
 </p>
 
 <p class=description>
-Returns the time in seconds, relative to the origin of the 
-universe. You should subtract the values returned by this function
+Returns the UNIX time in seconds. You should subtract the values returned by this function
 to get meaningful values. 
 </p>
 
@@ -117,29 +153,6 @@ t = socket.gettime()
 print(socket.gettime() - t .. " seconds elapsed")
 </pre>
 
-<!-- socket.headers ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class=name id="headers.canonic">
-socket.headers.<b>canonic</b></p>
-
-<p> The <tt>socket.headers.canonic</tt> table 
-is used by the HTTP and SMTP modules to translate from 
-lowercase field names back into their canonic 
-capitalization. When a lowercase field name exists as a key
-in this table, the associated value is substituted in
-whenever the field name is sent out.
-</p>
-
-<p> 
-You can obtain the <tt>headers</tt> namespace if case run-time
-modifications are required by running:
-</p>
-
-<pre class=example>
--- loads the headers module 
-local headers = require("headers")
-</pre>
-
 <!-- newtry +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class=name id=newtry> 
@@ -155,8 +168,7 @@ is  raised.
 
 <p class=parameters> 
 <tt>Finalizer</tt> is a function that will be called before
-<tt>try</tt> throws the exception. It will be called 
-in <em>protected</em> mode.
+<tt>try</tt> throws the exception.
 </p>
 
 <p class=return> 
@@ -204,15 +216,9 @@ to throw exceptions.
 </p>
 
 <p class=return>
-Returns an equivalent function that instead of throwing exceptions,
-returns <tt><b>nil</b></tt> followed by an error message. 
-</p>
-
-<p class=note>
-Note: Beware that if your function performs some illegal operation that
-raises an error, the protected function will catch the error and return it
-as a string. This is because the <a href=#try><tt>try</tt></a> function
-uses errors as the mechanism to throw exceptions.  
+Returns an equivalent function that instead of throwing exceptions in case of
+a failed <a href=#try><tt>try</tt></a> call, returns <tt><b>nil</b></tt>
+followed by an error message.
 </p>
 
 <!-- select +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -238,7 +244,9 @@ non-numeric indices) in the arrays will be silently ignored.
 
 <p class=return> The function returns a list with the sockets ready for
 reading, a list with the sockets ready for writing and an error message.
-The error message is "<tt>timeout</tt>" if a timeout condition was met and
+The error message is "<tt>timeout</tt>" if a timeout
+condition was met, "<tt>select failed</tt>" if the call
+to <tt>select</tt> failed, and
 <tt><b>nil</b></tt> otherwise. The returned tables are
 doubly keyed both by integers and also by the sockets
 themselves, to simplify the test if a specific socket has
@@ -246,7 +254,7 @@ changed status.
 </p>
 
 <p class=note>
-<b>Note: </b>: <tt>select</tt> can monitor a limited number
+<b>Note:</b> <tt>select</tt> can monitor a limited number
 of sockets, as defined by the constant <tt>socket._SETSIZE</tt>. This
 number may be as high as 1024 or as low as 64 by default,
 depending on the system. It is usually possible to change this
@@ -276,6 +284,18 @@ it to <tt>select</tt>, it will be ignored.
 <b>Using select with non-socket objects</b>: Any object that implements <tt>getfd</tt> and <tt>dirty</tt> can be used with <tt>select</tt>, allowing objects from other libraries to be used within a <tt>socket.select</tt> driven loop.
 </p>
 
+<!-- setsize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id=setsize> 
+socket.<b>_SETSIZE</b>
+</p>
+
+<p class=description>
+The maximum number of sockets that the <a
+href=#select><tt>select</tt></a> function can handle. 
+</p>
+
+
 <!-- sink ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class=name id=sink> 
@@ -383,15 +403,14 @@ side closes the connection.
 The function returns a source with the appropriate behavior. 
 </p>
 
-<!-- setsize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<!-- socketinvalid ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<p class=name id=setsize> 
-socket.<b>_SETSIZE</b>
+<p class=name id=socketinvalid>
+socket.<b>_SOCKETINVALID</b>
 </p>
 
 <p class=description>
-The maximum number of sockets that the <a
-href=#select><tt>select</tt></a> function can handle. 
+The OS value for an invalid socket.
 </p>
 
 <!-- try ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -401,9 +420,9 @@ socket.<b>try(</b>ret<sub>1</sub> [, ret<sub>2</sub> ... ret<sub>N</sub>]<b>)</b
 </p>
 
 <p class=description>
-Throws an exception in case of error. The exception can only be caught 
-by the <a href=#protect><tt>protect</tt></a> function. It does not explode
-into an error message.
+Throws an exception in case <tt>ret<sub>1</sub></tt> is falsy, using
+<tt>ret<sub>2</sub></tt> as the error message. The exception is supposed to be caught 
+by a <a href=#protect><tt>protect</tt></a>ed function only.
 </p>
 
 <p class=parameters>
@@ -414,7 +433,10 @@ nested with <tt>try</tt>.
 
 <p class=return> 
 The function returns <tt>ret</tt><sub>1</sub> to <tt>ret</tt><sub>N</sub> if
-<tt>ret</tt><sub>1</sub> is not <tt><b>nil</b></tt>. Otherwise, it calls <tt>error</tt> passing <tt>ret</tt><sub>2</sub>.
+<tt>ret</tt><sub>1</sub> is not <tt><b>nil</b></tt> or <tt><b>false</b></tt>.
+Otherwise, it calls <tt>error</tt> passing <tt>ret</tt><sub>2</sub> wrapped
+in a table with metatable used by <a href=#protect><tt>protect</tt></a> to
+distinguish exceptions from runtime errors.
 </p>
 
 <pre class=example>
diff --git a/doc/tcp.html b/doc/tcp.html
index 4226d78..c6c6eb2 100644
--- a/doc/tcp.html
+++ b/doc/tcp.html
@@ -1,10 +1,10 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
     "http://www.w3.org/TR/html4/strict.dtd">
 <html>
 
 <head>
 <meta name="description" content="LuaSocket: The TCP/IP support">
-<meta name="keywords" content="Lua, LuaSocket, Socket, TCP, Library, Network, Support"> 
+<meta name="keywords" content="Lua, LuaSocket, Socket, TCP, Library, Network, Support">
 <title>LuaSocket: TCP/IP support</title>
 <link rel="stylesheet" href="reference.css" type="text/css">
 </head>
@@ -28,7 +28,7 @@
 <a href="index.html#download">download</a> &middot;
 <a href="installation.html">installation</a> &middot;
 <a href="introduction.html">introduction</a> &middot;
-<a href="reference.html">reference</a> 
+<a href="reference.html">reference</a>
 </p>
 </center>
 <hr>
@@ -36,56 +36,11 @@
 
 <!-- tcp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<h2 id="tcp">TCP</h2> 
-
-<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class=name id="socket.tcp"> 
-socket.<b>tcp()</b>
-</p>
-
-<p class=description> 
-Creates and returns an IPv4 TCP master object. A master object can
-be transformed into a server object with the method 
-<a href=#listen><tt>listen</tt></a> (after a call to <a
-href=#bind><tt>bind</tt></a>) or into a client object with 
-the method <a href=#connect><tt>connect</tt></a>. The only other 
-method supported by a master object is the 
-<a href=#close><tt>close</tt></a> method.</p>
-
-<p class=return>
-In case of success, a new master object is returned. In case of error,
-<b><tt>nil</tt></b> is returned, followed by an error message.
-</p>
-
-<!-- socket.tcp6 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class=name id="socket.tcp6"> 
-socket.<b>tcp6()</b>
-</p>
-
-<p class=description> 
-Creates and returns an IPv6 TCP master object. A master object can
-be transformed into a server object with the method 
-<a href=#listen><tt>listen</tt></a> (after a call to <a
-href=#bind><tt>bind</tt></a>) or into a client object with 
-the method <a href=#connect><tt>connect</tt></a>. The only other 
-method supported by a master object is the 
-<a href=#close><tt>close</tt></a> method.</p>
-
-<p class=return>
-In case of success, a new master object is returned. In case of error,
-<b><tt>nil</tt></b> is returned, followed by an error message.
-</p>
-
-<p class=note>
-Note: The TCP object returned will have the option
-"<tt>ipv6-v6only</tt>" set to <tt><b>true</b></tt>.
-</p>
+<h2 id="tcp">TCP</h2>
 
 <!-- accept +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<p class=name id="accept"> 
+<p class=name id="accept">
 server:<b>accept()</b>
 </p>
 
@@ -95,9 +50,9 @@ object and returns a client object representing that connection.
 </p>
 
 <p class=return>
-If a connection is successfully initiated, a client object is returned.  
+If a connection is successfully initiated, a client object is returned.
 If a  timeout condition  is  met,  the method  returns <b><tt>nil</tt></b>
-followed by the error string '<tt>timeout</tt>'. Other errors are 
+followed by the error string '<tt>timeout</tt>'. Other errors are
 reported by <b><tt>nil</tt></b> followed by a message describing the error.
 </p>
 
@@ -107,28 +62,28 @@ with   a  server   object   in
 the <tt>recvt</tt>  parameter  before  a   call  to  <tt>accept</tt> does
 <em>not</em> guarantee  <tt>accept</tt> will  return immediately.  Use the <a
 href=#settimeout><tt>settimeout</tt></a> method or <tt>accept</tt>
-might block until <em>another</em> client shows up. 
+might block until <em>another</em> client shows up.
 </p>
 
 <!-- bind +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<p class=name id="bind"> 
+<p class=name id="bind">
 master:<b>bind(</b>address, port<b>)</b>
 </p>
 
 <p class=description>
 Binds a master object to <tt>address</tt> and <tt>port</tt> on the
-local host. 
+local host.
 
 <p class=parameters>
-<tt>Address</tt> can be an IP address or a host name. 
-<tt>Port</tt> must be an integer number in the range [0..64K). 
+<tt>Address</tt> can be an IP address or a host name.
+<tt>Port</tt> must be an integer number in the range [0..64K).
 If <tt>address</tt>
 is '<tt>*</tt>', the system binds to all local interfaces
 using the <tt>INADDR_ANY</tt> constant or
-<tt>IN6ADDR_ANY_INIT</tt>, according to the family. 
+<tt>IN6ADDR_ANY_INIT</tt>, according to the family.
 If <tt>port</tt> is 0, the system automatically
-chooses an ephemeral port.  
+chooses an ephemeral port.
 </p>
 
 <p class=return>
@@ -137,13 +92,13 @@ method returns <b><tt>nil</tt></b> followed by an error message.
 </p>
 
 <p class=note>
-Note: The function <a href=socket.html#bind><tt>socket.bind</tt></a> 
+Note: The function <a href=socket.html#bind><tt>socket.bind</tt></a>
 is available and is a shortcut for the creation of server sockets.
 </p>
 
 <!-- close ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<p class=name id="close"> 
+<p class=name id="close">
 master:<b>close()</b><br>
 client:<b>close()</b><br>
 server:<b>close()</b>
@@ -154,14 +109,14 @@ Closes  a TCP object. The internal socket used by the object is closed
 and the local  address   to  which the object was
 bound is made  available to other  applications. No further  operations
 (except  for  further calls  to the <tt>close</tt> method)  are allowed on
-a closed socket. 
+a closed socket.
 </p>
 
 <p class=note>
 Note:  It is  important to  close all  used  sockets once  they are  not
 needed,  since, in  many systems,  each socket  uses a  file descriptor,
 which are limited system resources. Garbage-collected objects are
-automatically closed before destruction, though. 
+automatically closed before destruction, though.
 </p>
 
 <!-- connect ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -172,19 +127,19 @@ master:<b>connect(</b>address, port<b>)</b>
 
 <p class=description>
 Attempts to connect a master object to a remote host, transforming it into a
-client object. 
-Client objects support methods 
+client object.
+Client objects support methods
 <a href=#send><tt>send</tt></a>,
-<a href=#receive><tt>receive</tt></a>, 
-<a href=#getsockname><tt>getsockname</tt></a>, 
+<a href=#receive><tt>receive</tt></a>,
+<a href=#getsockname><tt>getsockname</tt></a>,
 <a href=#getpeername><tt>getpeername</tt></a>,
-<a href=#settimeout><tt>settimeout</tt></a>, 
+<a href=#settimeout><tt>settimeout</tt></a>,
 and <a href=#close><tt>close</tt></a>.
 </p>
 
 <p class=parameters>
-<tt>Address</tt> can be an IP address or a host name. 
-<tt>Port</tt> must be an integer number in the range [1..64K). 
+<tt>Address</tt> can be an IP address or a host name.
+<tt>Port</tt> must be an integer number in the range [1..64K).
 </p>
 
 <p class=return>
@@ -193,14 +148,14 @@ describing the error. In case of success, the method returns 1.
 </p>
 
 <p class=note>
-Note: The function <a href=socket.html#connect><tt>socket.connect</tt></a> 
+Note: The function <a href=socket.html#connect><tt>socket.connect</tt></a>
 is available and is a shortcut for the creation of client sockets.
 </p>
 
 <p class=note>
-Note: Starting with LuaSocket 2.0, 
+Note: Starting with LuaSocket 2.0,
 the <a href=#settimeout><tt>settimeout</tt></a>
-method affects the behavior of <tt>connect</tt>, causing it to return 
+method affects the behavior of <tt>connect</tt>, causing it to return
 with an error in case of a timeout. If that happens, you can still call <a
 href=socket.html#select><tt>socket.select</tt></a> with the socket in the
 <tt>sendt</tt> table. The socket will be writable when the connection is
@@ -209,13 +164,88 @@ established.
 
 <p class=note>
 Note: Starting with LuaSocket 3.0, the host name resolution
-depends on whether the socket was created by <a
-href=#socket.tcp><tt>socket.tcp</tt></a> or <a
-href=#socket.tcp6><tt>socket.tcp6</tt></a>. Addresses from
-the appropriate family are tried in succession until the
-first success or until the last failure.
+depends on whether the socket was created by
+<a href=#socket.tcp><tt>socket.tcp</tt></a>,
+<a href=#socket.tcp4><tt>socket.tcp4</tt></a> or
+<a href=#socket.tcp6><tt>socket.tcp6</tt></a>. Addresses from
+the appropriate family (or both) are tried in the order
+returned by the resolver until the
+first success or until the last failure. If the timeout was
+set to zero, only the first address is tried.
+</p>
+
+<!-- dirty +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="dirty">
+master:<b>dirty()</b><br>
+client:<b>dirty()</b><br>
+server:<b>dirty()</b>
+</p>
+
+<p class=description>
+Check the read buffer status.
+</p>
+
+<p class=return>
+Returns <tt>true</tt> if there is any data in the read buffer, <tt>false</tt> otherwise.
+</p>
+
+<p class=note>
+Note: <b>This is an internal method, use at your own risk.</b>
+</p>
+
+
+<!-- getfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="getfd">
+master:<b>getfd()</b><br>
+client:<b>getfd()</b><br>
+server:<b>getfd()</b>
+</p>
+
+<p class=description>
+Returns the underling socket descriptor or handle associated to the object.
+</p>
+
+<p class=return>
+The descriptor or handle. In case the object has been closed, the return will be -1.
+</p>
+
+<p class=note>
+Note: <b>This is an internal method. Unlikely to be
+portable. Use at your own risk. </b>
+</p>
+
+
+<!-- getoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="getoption">
+client:<b>getoption(</b>option)</b><br>
+server:<b>getoption(</b>option)</b>
+</p>
+
+<p class=description>
+Gets options for the TCP object.
+See <a href=#setoption><tt>setoption</tt></a> for description of the
+option names and values.
+</p>
+
+<p class=parameters>
+<tt>Option</tt> is a string with the option name.
+<ul>
+
+<li> '<tt>keepalive</tt>'
+<li> '<tt>linger</tt>'
+<li> '<tt>reuseaddr</tt>'
+<li> '<tt>tcp-nodelay</tt>'
+</ul>
+
+<p class=return>
+The method returns the option <tt>value</tt> in case of success, or
+<b><tt>nil</tt></b> followed by an error message otherwise.
 </p>
 
+
 <!-- getpeername ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class=name id="getpeername">
@@ -227,10 +257,10 @@ Returns information about the remote side of a connected client object.
 </p>
 
 <p class=return>
-Returns a string with the IP address of the peer, the 
-port number that peer is using for the connection, 
-and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). 
-In case of error, the method returns <b><tt>nil</tt></b>. 
+Returns a string with the IP address of the peer, the
+port number that peer is using for the connection,
+and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>").
+In case of error, the method returns <b><tt>nil</tt></b>.
 </p>
 
 <p class=note>
@@ -246,13 +276,13 @@ server:<b>getsockname()</b>
 </p>
 
 <p class=description>
-Returns the local address information associated to the object. 
+Returns the local address information associated to the object.
 </p>
 
 <p class=return>
-The method returns a string with local IP address, a number with 
-the local port, 
-and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). 
+The method returns a string with local IP address, a number with
+the local port,
+and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>").
 In case of error, the method returns <b><tt>nil</tt></b>.
 </p>
 
@@ -266,32 +296,46 @@ server:<b>getstats()</b><br>
 
 <p class=description>
 Returns accounting information on the socket, useful for throttling
-of bandwidth. 
+of bandwidth.
 </p>
 
 <p class=return>
 The method returns the number of bytes received, the number of bytes sent,
-and the age of the socket object in seconds. 
+and the age of the socket object in seconds.
 </p>
 
+<!-- gettimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="gettimeout">
+master:<b>gettimeout()</b><br>
+client:<b>gettimeout()</b><br>
+server:<b>gettimeout()</b>
+</p>
+
+<p class=description>
+Returns the current block timeout followed by the curent
+total timeout.
+</p>
+
+
 <!-- listen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<p class=name id="listen"> 
+<p class=name id="listen">
 master:<b>listen(</b>backlog<b>)</b>
 </p>
 
 <p class=description>
 Specifies the socket is willing to receive connections, transforming the
-object into a server object.  Server objects support the 
-<a href=#accept><tt>accept</tt></a>,  
-<a href=#getsockname><tt>getsockname</tt></a>, 
-<a href=#setoption><tt>setoption</tt></a>, 
-<a href=#settimeout><tt>settimeout</tt></a>, 
-and <a href=#close><tt>close</tt></a> methods.  
+object into a server object.  Server objects support the
+<a href=#accept><tt>accept</tt></a>,
+<a href=#getsockname><tt>getsockname</tt></a>,
+<a href=#setoption><tt>setoption</tt></a>,
+<a href=#settimeout><tt>settimeout</tt></a>,
+and <a href=#close><tt>close</tt></a> methods.
 </p>
 
 <p class=parameters>
-The parameter <tt>backlog</tt> specifies the  number  of  client 
+The parameter <tt>backlog</tt> specifies the  number  of  client
 connections that can
 be queued waiting for service. If the queue is full and another  client
 attempts connection,  the connection is  refused.
@@ -310,11 +354,11 @@ client:<b>receive(</b>[pattern [, prefix]]<b>)</b>
 
 <p class=description>
 Reads data from a client object, according to the specified <em>read
-pattern</em>.  Patterns follow the Lua file I/O format, and the difference in performance between all patterns is negligible. 
+pattern</em>.  Patterns follow the Lua file I/O format, and the difference in performance between all patterns is negligible.
 </p>
 
 <p class=parameters>
-<tt>Pattern</tt> can be any of the following: 
+<tt>Pattern</tt> can be any of the following:
 </p>
 
 <ul>
@@ -325,7 +369,7 @@ terminated by a  LF character (ASCII&nbsp;10), optionally  preceded by a
 CR character (ASCII&nbsp;13). The CR and LF characters are not included in
 the returned line. In fact, <em>all</em> CR characters are
 ignored by the pattern. This is the default pattern;
-<li> <tt>number</tt>:  causes the  method to read  a specified <tt>number</tt> 
+<li> <tt>number</tt>:  causes the  method to read  a specified <tt>number</tt>
 of bytes from the socket.
 </ul>
 
@@ -347,10 +391,10 @@ closed  before  the transmission  was completed  or  the string
 <p class=note>
 <b>Important note</b>: This function was changed <em>severely</em>. It used
 to support multiple patterns (but I have never seen this feature used) and
-now it doesn't anymore.  Partial results used to be returned in the same 
+now it doesn't anymore.  Partial results used to be returned in the same
 way as successful results. This last feature violated the idea that all
 functions should return <tt><b>nil</b></tt> on error.  Thus it was changed
-too. 
+too.
 </p>
 
 <!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -366,7 +410,7 @@ Sends <tt>data</tt> through client object.
 <p class=parameters>
 <tt>Data</tt> is the string to be sent. The optional arguments
 <tt>i</tt> and <tt>j</tt> work exactly like the standard
-<tt>string.sub</tt> Lua function to allow the selection of a 
+<tt>string.sub</tt> Lua function to allow the selection of a
 substring to be sent.
 </p>
 
@@ -385,10 +429,10 @@ there was  a  timeout  during  the operation.
 </p>
 
 <p class=note>
-Note: Output is <em>not</em> buffered. For small strings, 
-it is always better to concatenate them in Lua 
-(with the '<tt>..</tt>' operator) and send the result in one call 
-instead of calling the method several times. 
+Note: Output is <em>not</em> buffered. For small strings,
+it is always better to concatenate them in Lua
+(with the '<tt>..</tt>' operator) and send the result in one call
+instead of calling the method several times.
 </p>
 
 <!-- setoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -400,12 +444,12 @@ server:<b>setoption(</b>option [, value]<b>)</b>
 
 <p class=description>
 Sets options for the TCP object. Options are only needed by low-level or
-time-critical applications. You should only modify an option if you 
-are sure you need it. 
+time-critical applications. You should only modify an option if you
+are sure you need it.
 </p>
 
 <p class=parameters>
-<tt>Option</tt> is a string with the option name, and <tt>value</tt> 
+<tt>Option</tt> is a string with the option name, and <tt>value</tt>
 depends on the option being set:
 
 <ul>
@@ -413,7 +457,7 @@ depends on the option being set:
 <li> '<tt>keepalive</tt>':  Setting this option to <tt>true</tt> enables
 the periodic transmission of messages on a connected socket. Should the
 connected party fail to respond to these messages, the connection is
-considered broken and processes using the socket are notified; 
+considered broken and processes using the socket are notified;
 
 <li> '<tt>linger</tt>': Controls the action taken when unsent data are
 queued on a socket and a close is performed.  The value is a table with a
@@ -424,13 +468,13 @@ it is able to transmit the data or until '<tt>timeout</tt>' has passed. If
 '<tt>on</tt>' is <tt>false</tt> and a close is issued, the system will
 process the close in a manner that allows the process to continue as
 quickly as possible. I do not advise you to set this to anything other than
-zero; 
+zero;
 
 <li> '<tt>reuseaddr</tt>': Setting this option indicates that the rules
-used in validating addresses supplied in a call to 
+used in validating addresses supplied in a call to
 <a href=#bind><tt>bind</tt></a> should allow reuse of local addresses;
 
-<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt> 
+<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt>
 disables the Nagle's algorithm for the connection;
 
 <li> '<tt>ipv6-v6only</tt>':
@@ -447,34 +491,6 @@ followed by an error message otherwise.
 Note: The descriptions above come from the man pages.
 </p>
 
-<!-- getoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class=name id="getoption">
-client:<b>getoption(</b>option)</b><br>
-server:<b>getoption(</b>option)</b>
-</p>
-
-<p class=description>
-Gets options for the TCP object.
-See <a href=#setoption><tt>setoption</tt></a> for description of the
-option names and values.
-</p>
-
-<p class=parameters>
-<tt>Option</tt> is a string with the option name.
-<ul>
-
-<li> '<tt>keepalive</tt>'
-<li> '<tt>linger</tt>'
-<li> '<tt>reuseaddr</tt>'
-<li> '<tt>tcp-nodelay</tt>'
-</ul>
-
-<p class=return>
-The method returns the option <tt>value</tt> in case of success, or
-<b><tt>nil</tt></b> followed by an error message otherwise.
-</p>
-
 <!-- setstats +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class=name id="setstats">
@@ -485,7 +501,7 @@ server:<b>setstats(</b>received, sent, age<b>)</b><br>
 
 <p class=description>
 Resets accounting information on the socket, useful for throttling
-of bandwidth. 
+of bandwidth.
 </p>
 
 <p class=parameters>
@@ -495,7 +511,7 @@ of bandwidth.
 </p>
 
 <p class=return>
-The method returns 1 in case of success and <tt><b>nil</b></tt> otherwise. 
+The method returns 1 in case of success and <tt><b>nil</b></tt> otherwise.
 </p>
 
 <!-- settimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -509,8 +525,8 @@ server:<b>settimeout(</b>value [, mode]<b>)</b>
 <p class=description>
 Changes the timeout  values for the object. By default,
 all I/O  operations are  blocking. That  is, any  call to  the methods
-<a href=#send><tt>send</tt></a>, 
-<a href=#receive><tt>receive</tt></a>, and 
+<a href=#send><tt>send</tt></a>,
+<a href=#receive><tt>receive</tt></a>, and
 <a href=#accept><tt>accept</tt></a>
 will  block indefinitely,  until the operation completes.  The
 <tt>settimeout</tt>  method defines a  limit on the  amount  of   time  the
@@ -521,7 +537,7 @@ time has elapsed, the affected methods give up and fail with an error code.
 <p class=parameters>
 The amount of time to wait is specified  as  the
 <tt>value</tt> parameter, in seconds. There  are two timeout  modes and
-both can be used together for fine tuning: 
+both can be used together for fine tuning:
 </p>
 
 <ul>
@@ -532,7 +548,7 @@ default mode;</li>
 
 <li> '<tt>t</tt>':  <em>total</em> timeout. Specifies the  upper limit on
 the amount of  time LuaSocket can block a Lua  script before returning from
-a call.</li> 
+a call.</li>
 </ul>
 
 <p class=parameters>
@@ -562,7 +578,7 @@ client:<b>shutdown(</b>mode<b>)</b><br>
 </p>
 
 <p class=description>
-Shuts down part of a full-duplex connection. 
+Shuts down part of a full-duplex connection.
 </p>
 
 <p class=parameters>
@@ -579,66 +595,107 @@ This is the default mode;
 This function returns 1.
 </p>
 
-<!-- dirty +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<!-- setfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<p class=name id="dirty">
-master:<b>dirty()</b><br>
-client:<b>dirty()</b><br>
-server:<b>dirty()</b>
+<p class=name id="setfd">
+master:<b>setfd(</b>fd<b>)</b><br>
+client:<b>setfd(</b>fd<b>)</b><br>
+server:<b>setfd(</b>fd<b>)</b>
 </p>
 
 <p class=description>
-Check the read buffer status.
+Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made.
 </p>
 
 <p class=return>
-Returns <tt>true</tt> if there is any data in the read buffer, <tt>false</tt> otherwise.
+No return value.
 </p>
 
 <p class=note>
-Note: <b>This is an internal method, any use is unlikely to be portable.</b>
+Note: <b>This is an internal method. Unlikely to be
+portable. Use at your own risk. </b>
 </p>
 
-<!-- getfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<p class=name id="getfd">
-master:<b>getfd()</b><br>
-client:<b>getfd()</b><br>
-server:<b>getfd()</b>
+<p class=name id="socket.tcp">
+socket.<b>tcp()</b>
 </p>
 
 <p class=description>
-Returns the underling socket descriptor or handle associated to the object. 
-</p>
+Creates and returns an TCP master object. A master object can
+be transformed into a server object with the method
+<a href=#listen><tt>listen</tt></a> (after a call to <a
+href=#bind><tt>bind</tt></a>) or into a client object with
+the method <a href=#connect><tt>connect</tt></a>. The only other
+method supported by a master object is the
+<a href=#close><tt>close</tt></a> method.</p>
 
 <p class=return>
-The descriptor or handle. In case the object has been closed, the return will be -1.
+In case of success, a new master object is returned. In case of error,
+<b><tt>nil</tt></b> is returned, followed by an error message.
 </p>
 
 <p class=note>
-Note: <b>This is an internal method, any use is unlikely to be portable.</b>
+Note: The choice between IPv4 and IPv6 happens during a call to
+<a href=#bind><tt>bind</tt></a> or <a
+href=#bind><tt>connect</tt></a>, depending on the address
+family obtained from the resolver.
 </p>
 
-<!-- setfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<p class=note>
+Note: Before the choice between IPv4 and IPv6 happens,
+the internal socket object is invalid and therefore <a
+href=#setoption><tt>setoption</tt></a> will fail.
+</p>
 
-<p class=name id="setfd">
-master:<b>setfd(</b>fd<b>)</b><br>
-client:<b>setfd(</b>fd<b>)</b><br>
-server:<b>setfd(</b>fd<b>)</b>
+<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="socket.tcp4">
+socket.<b>tcp4()</b>
 </p>
 
 <p class=description>
-Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made.
+Creates and returns an IPv4 TCP master object. A master object can
+be transformed into a server object with the method
+<a href=#listen><tt>listen</tt></a> (after a call to <a
+href=#bind><tt>bind</tt></a>) or into a client object with
+the method <a href=#connect><tt>connect</tt></a>. The only other
+method supported by a master object is the
+<a href=#close><tt>close</tt></a> method.</p>
+
+<p class=return>
+In case of success, a new master object is returned. In case of error,
+<b><tt>nil</tt></b> is returned, followed by an error message.
+</p>
+
+<!-- socket.tcp6 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="socket.tcp6">
+socket.<b>tcp6()</b>
 </p>
 
+<p class=description>
+Creates and returns an IPv6 TCP master object. A master object can
+be transformed into a server object with the method
+<a href=#listen><tt>listen</tt></a> (after a call to <a
+href=#bind><tt>bind</tt></a>) or into a client object with
+the method <a href=#connect><tt>connect</tt></a>. The only other
+method supported by a master object is the
+<a href=#close><tt>close</tt></a> method.</p>
+
 <p class=return>
-No return value.
+In case of success, a new master object is returned. In case of error,
+<b><tt>nil</tt></b> is returned, followed by an error message.
 </p>
 
 <p class=note>
-Note: <b>This is an internal method, any use is unlikely to be portable.</b>
+Note: The TCP object returned will have the option
+"<tt>ipv6-v6only</tt>" set to <tt><b>true</b></tt>.
 </p>
 
+
+
 <!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <div class=footer>
diff --git a/doc/udp.html b/doc/udp.html
index e5b0ad0..4618aad 100644
--- a/doc/udp.html
+++ b/doc/udp.html
@@ -4,7 +4,7 @@
 
 <head>
 <meta name="description" content="LuaSocket: The UDP support">
-<meta name="keywords" content="Lua, LuaSocket, Socket, UDP, Library, Network, Support"> 
+<meta name="keywords" content="Lua, LuaSocket, Socket, UDP, Library, Network, Support">
 <title>LuaSocket: UDP support</title>
 <link rel="stylesheet" href="reference.css" type="text/css">
 </head>
@@ -28,7 +28,7 @@
 <a href="index.html#download">download</a> &middot;
 <a href="installation.html">installation</a> &middot;
 <a href="introduction.html">introduction</a> &middot;
-<a href="reference.html">reference</a> 
+<a href="reference.html">reference</a>
 </p>
 </center>
 <hr>
@@ -37,74 +37,7 @@
 
 <!-- udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
-<h2 id="udp">UDP</h2> 
-
-<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class="name" id="socket.udp">
-socket.<b>udp()</b>
-</p>
-
-<p class="description">
-Creates and returns an unconnected IPv4 UDP object. 
-Unconnected objects support the 
-<a href="#sendto"><tt>sendto</tt></a>, 
-<a href="#receive"><tt>receive</tt></a>, 
-<a href="#receivefrom"><tt>receivefrom</tt></a>, 
-<a href="#getoption"><tt>getoption</tt></a>, 
-<a href="#getsockname"><tt>getsockname</tt></a>, 
-<a href="#setoption"><tt>setoption</tt></a>, 
-<a href="#settimeout"><tt>settimeout</tt></a>, 
-<a href="#setpeername"><tt>setpeername</tt></a>, 
-<a href="#setsockname"><tt>setsockname</tt></a>, and 
-<a href="#close"><tt>close</tt></a>. 
-The <a href="#setpeername"><tt>setpeername</tt></a> 
-is used to connect the object.
-</p>
-
-<p class="return">
-In case of success, a new unconnected UDP object
-returned. In case of error, <b><tt>nil</tt></b> is returned, followed by
-an error message.
-</p>
-
-<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class="name" id="socket.udp6">
-socket.<b>udp6()</b>
-</p>
-
-<p class="description">
-Creates and returns an unconnected IPv6 UDP object. 
-Unconnected objects support the 
-<a href="#sendto"><tt>sendto</tt></a>, 
-<a href="#receive"><tt>receive</tt></a>, 
-<a href="#receivefrom"><tt>receivefrom</tt></a>, 
-<a href="#getoption"><tt>getoption</tt></a>, 
-<a href="#getsockname"><tt>getsockname</tt></a>, 
-<a href="#setoption"><tt>setoption</tt></a>, 
-<a href="#settimeout"><tt>settimeout</tt></a>, 
-<a href="#setpeername"><tt>setpeername</tt></a>, 
-<a href="#setsockname"><tt>setsockname</tt></a>, and 
-<a href="#close"><tt>close</tt></a>. 
-The <a href="#setpeername"><tt>setpeername</tt></a> 
-is used to connect the object.
-</p>
-
-<p class="return">
-In case of success, a new unconnected UDP object
-returned. In case of error, <b><tt>nil</tt></b> is returned, followed by
-an error message.
-</p>
-
-<p class=note>
-Note: The TCP object returned will have the option
-"<tt>ipv6-v6only</tt>" set to <tt><b>true</b></tt>.
-</p>
-
-
-
-<!-- close +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<h2 id="udp">UDP</h2>
 
 <!-- close +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
@@ -129,6 +62,40 @@ Garbage-collected objects are automatically closed before
 destruction, though.
 </p>
 
+<!-- getoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class="name" id="getoption">
+connected:<b>getoption()</b><br>
+unconnected:<b>getoption()</b>
+</p>
+
+<p class="description">
+Gets an option value from the UDP object.
+See <a href=#setoption><tt>setoption</tt></a> for
+description of the option names and values.
+</p>
+
+<p class="parameters"><tt>Option</tt> is a string with the option name.
+<ul>
+<li> '<tt>dontroute</tt>'
+<li> '<tt>broadcast</tt>'
+<li> '<tt>reuseaddr</tt>'
+<li> '<tt>reuseport</tt>'
+<li> '<tt>ip-multicast-loop</tt>'
+<li> '<tt>ipv6-v6only</tt>'
+<li> '<tt>ip-multicast-if</tt>'
+<li> '<tt>ip-multicast-ttl</tt>'
+<li> '<tt>ip-add-membership</tt>'
+<li> '<tt>ip-drop-membership</tt>'
+</ul>
+</p>
+
+<p class=return>
+The method returns the option <tt>value</tt> in case of
+success, or
+<b><tt>nil</tt></b> followed by an error message otherwise.
+</p>
+
 <!-- getpeername +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class="name" id="getpeername">
@@ -142,10 +109,10 @@ associated with a connected UDP object.
 
 
 <p class=return>
-Returns a string with the IP address of the peer, the 
-port number that peer is using for the connection, 
-and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). 
-In case of error, the method returns <b><tt>nil</tt></b>. 
+Returns a string with the IP address of the peer, the
+port number that peer is using for the connection,
+and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>").
+In case of error, the method returns <b><tt>nil</tt></b>.
 </p>
 
 <p class="note">
@@ -165,9 +132,9 @@ Returns the local address information associated to the object.
 
 
 <p class=return>
-The method returns a string with local IP address, a number with 
-the local port, 
-and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). 
+The method returns a string with local IP address, a number with
+the local port,
+and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>").
 In case of error, the method returns <b><tt>nil</tt></b>.
 </p>
 
@@ -179,6 +146,18 @@ first time (in which case it is bound to an ephemeral port and the
 wild-card address).
 </p>
 
+<!-- gettimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class=name id="gettimeout">
+connected:<b>settimeout(</b>value<b>)</b><br>
+unconnected:<b>settimeout(</b>value<b>)</b>
+</p>
+
+<p class=description>
+Returns the current timeout value.
+</p>
+
+
 <!-- receive +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class="name" id="receive">
@@ -199,9 +178,12 @@ specifies the maximum size of the datagram to be retrieved. If
 there are more than <tt>size</tt> bytes available in the datagram,
 the excess bytes are discarded. If there are less then
 <tt>size</tt> bytes available in the current datagram, the
-available bytes are returned. If <tt>size</tt> is omitted, the
-maximum datagram size is used (which is currently limited by the
-implementation to 8192 bytes).
+available bytes are returned.
+If <tt>size</tt> is omitted, the
+compile-time constant <a
+href=socket.html#datagramsize><tt>socket._DATAGRAMSIZE</tt></a> is used
+(it defaults to 8192 bytes). Larger sizes will cause a
+temporary buffer to be allocated for the operation.
 </p>
 
 <p class="return">
@@ -217,46 +199,12 @@ unconnected:<b>receivefrom(</b>[size]<b>)</b>
 </p>
 
 <p class="description">
-Works exactly as the <a href="#receive"><tt>receive</tt></a> 
+Works exactly as the <a href="#receive"><tt>receive</tt></a>
 method, except it returns the IP
 address and port as extra return values (and is therefore slightly less
 efficient).
 </p>
 
-<!-- getoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class="name" id="getoption">
-connected:<b>getoption()</b><br>
-unconnected:<b>getoption()</b>
-</p>
-
-<p class="description">
-Gets an option value from the UDP object.
-See <a href=#setoption><tt>setoption</tt></a> for
-description of the option names and values.
-</p>
-
-<p class="parameters"><tt>Option</tt> is a string with the option name. 
-<ul>
-<li> '<tt>dontroute</tt>'
-<li> '<tt>broadcast</tt>'
-<li> '<tt>reuseaddr</tt>'
-<li> '<tt>reuseport</tt>'
-<li> '<tt>ip-multicast-loop</tt>'
-<li> '<tt>ipv6-v6only</tt>'
-<li> '<tt>ip-multicast-if</tt>'
-<li> '<tt>ip-multicast-ttl</tt>'
-<li> '<tt>ip-add-membership</tt>' 
-<li> '<tt>ip-drop-membership</tt>'
-</ul> 
-</p>
-
-<p class=return>
-The method returns the option <tt>value</tt> in case of
-success, or
-<b><tt>nil</tt></b> followed by an error message otherwise.
-</p>
-
 <!-- send ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class="name" id="send">
@@ -268,7 +216,7 @@ Sends a datagram to the UDP peer of a connected object.
 </p>
 
 <p class="parameters">
-<tt>Datagram</tt> is a string with the datagram contents. 
+<tt>Datagram</tt> is a string with the datagram contents.
 The maximum datagram size for UDP is 64K minus IP layer overhead.
 However datagrams larger than the link layer packet size will be
 fragmented, which may deteriorate performance and/or reliability.
@@ -298,11 +246,11 @@ Sends a datagram to the specified IP address and port number.
 
 <p class="parameters">
 <tt>Datagram</tt> is a string with the
-datagram contents. 
+datagram contents.
 The maximum datagram size for UDP is 64K minus IP layer overhead.
 However datagrams larger than the link layer packet size will be
 fragmented, which may deteriorate performance and/or reliability.
-<tt>Ip</tt> is the IP address of the recipient. 
+<tt>Ip</tt> is the IP address of the recipient.
 Host names are <em>not</em> allowed for performance reasons.
 
 <tt>Port</tt> is the port number at the recipient.
@@ -320,6 +268,75 @@ refuses to send a message to the specified address (i.e. no
 interface accepts the address).
 </p>
 
+<!-- setoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class="name" id="setoption">
+connected:<b>setoption(</b>option [, value]<b>)</b><br>
+unconnected:<b>setoption(</b>option [, value]<b>)</b>
+</p>
+
+<p class="description">
+Sets options for the UDP object. Options are
+only needed by low-level or time-critical applications. You should
+only modify an option if you are sure you need it.</p>
+<p class="parameters"><tt>Option</tt> is a string with the option
+name, and <tt>value</tt> depends on the option being set:
+</p>
+
+<ul>
+<li> '<tt>dontroute</tt>': Indicates that outgoing
+messages should bypass the standard routing facilities.
+Receives a boolean value;
+<li> '<tt>broadcast</tt>': Requests permission to send
+broadcast datagrams on the socket.
+Receives a boolean value;
+<li> '<tt>reuseaddr</tt>': Indicates that the rules used in
+validating addresses supplied in a <tt>bind()</tt> call
+should allow reuse of local addresses.
+Receives a boolean value;
+<li> '<tt>reuseport</tt>': Allows completely duplicate
+bindings by multiple processes if they all set
+'<tt>reuseport</tt>' before binding the port.
+Receives a boolean value;
+<li> '<tt>ip-multicast-loop</tt>':
+Specifies whether or not a copy of an outgoing multicast
+datagram is delivered to the sending host as long as it is a
+member of the multicast group.
+Receives a boolean value;
+<li> '<tt>ipv6-v6only</tt>':
+Specifies whether to restrict <tt>inet6</tt> sockets to
+sending and receiving only IPv6 packets.
+Receive a boolean value;
+<li> '<tt>ip-multicast-if</tt>':
+Sets the interface over which outgoing multicast datagrams
+are sent.
+Receives an IP address;
+<li> '<tt>ip-multicast-ttl</tt>':
+Sets the Time To Live in the IP header for outgoing
+multicast datagrams.
+Receives a number;
+<li> '<tt>ip-add-membership</tt>':
+Joins the multicast group specified.
+Receives a table with fields
+<tt>multiaddr</tt> and <tt>interface</tt>, each containing an
+IP address;
+<li> '<tt>ip-drop-membership</tt>': Leaves the multicast
+group specified.
+Receives a table with fields
+<tt>multiaddr</tt> and <tt>interface</tt>, each containing an
+IP address.
+</ul>
+
+<p class="return">
+The method returns 1 in case of success, or
+<b><tt>nil</tt></b> followed by an error message otherwise.
+</p>
+
+<p class=note>
+Note: The descriptions above come from the man pages.
+</p>
+
+
 <!-- setpeername +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class="name" id="setpeername">
@@ -337,9 +354,9 @@ object or vice versa.
 For connected objects, outgoing datagrams
 will be sent to the specified peer, and datagrams received from
 other peers will be discarded by the OS. Connected UDP objects must
-use the <a href="#send"><tt>send</tt></a> and 
-<a href="#receive"><tt>receive</tt></a> methods instead of 
-<a href="#sendto"><tt>sendto</tt></a> and 
+use the <a href="#send"><tt>send</tt></a> and
+<a href="#receive"><tt>receive</tt></a> methods instead of
+<a href="#sendto"><tt>sendto</tt></a> and
 <a href="#receivefrom"><tt>receivefrom</tt></a>.
 </p>
 
@@ -406,74 +423,6 @@ system or explicitly by <tt>setsockname</tt>, it cannot be
 changed.
 </p>
 
-<!-- setoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-<p class="name" id="setoption">
-connected:<b>setoption(</b>option [, value]<b>)</b><br>
-unconnected:<b>setoption(</b>option [, value]<b>)</b>
-</p>
-
-<p class="description">
-Sets options for the UDP object. Options are
-only needed by low-level or time-critical applications. You should
-only modify an option if you are sure you need it.</p>
-<p class="parameters"><tt>Option</tt> is a string with the option
-name, and <tt>value</tt> depends on the option being set:
-</p>
-
-<ul> 
-<li> '<tt>dontroute</tt>': Indicates that outgoing
-messages should bypass the standard routing facilities.
-Receives a boolean value;
-<li> '<tt>broadcast</tt>': Requests permission to send 
-broadcast datagrams on the socket.
-Receives a boolean value;
-<li> '<tt>reuseaddr</tt>': Indicates that the rules used in
-validating addresses supplied in a <tt>bind()</tt> call 
-should allow reuse of local addresses. 
-Receives a boolean value;
-<li> '<tt>reuseport</tt>': Allows completely duplicate
-bindings by multiple processes if they all set
-'<tt>reuseport</tt>' before binding the port.
-Receives a boolean value;
-<li> '<tt>ip-multicast-loop</tt>':
-Specifies whether or not a copy of an outgoing multicast
-datagram is delivered to the sending host as long as it is a
-member of the multicast group.
-Receives a boolean value;
-<li> '<tt>ipv6-v6only</tt>':
-Specifies whether to restrict <tt>inet6</tt> sockets to 
-sending and receiving only IPv6 packets.
-Receive a boolean value;
-<li> '<tt>ip-multicast-if</tt>':
-Sets the interface over which outgoing multicast datagrams
-are sent.
-Receives an IP address;
-<li> '<tt>ip-multicast-ttl</tt>':
-Sets the Time To Live in the IP header for outgoing
-multicast datagrams. 
-Receives a number;
-<li> '<tt>ip-add-membership</tt>': 
-Joins the multicast group specified.
-Receives a table with fields
-<tt>multiaddr</tt> and <tt>interface</tt>, each containing an
-IP address;
-<li> '<tt>ip-drop-membership</tt>': Leaves the multicast
-group specified.
-Receives a table with fields
-<tt>multiaddr</tt> and <tt>interface</tt>, each containing an
-IP address.
-</ul> 
-
-<p class="return">
-The method returns 1 in case of success, or
-<b><tt>nil</tt></b> followed by an error message otherwise.
-</p>
-
-<p class=note>
-Note: The descriptions above come from the man pages.
-</p>
-
 <!-- settimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <p class="name" id="settimeout">
@@ -482,14 +431,14 @@ unconnected:<b>settimeout(</b>value<b>)</b>
 </p>
 
 <p class="description">
-Changes the timeout values for the object.  By default, the 
-<a href="#receive"><tt>receive</tt></a> and 
-<a href="#receivefrom"><tt>receivefrom</tt></a> 
+Changes the timeout values for the object.  By default, the
+<a href="#receive"><tt>receive</tt></a> and
+<a href="#receivefrom"><tt>receivefrom</tt></a>
 operations are blocking. That is, any call to the methods will block
 indefinitely, until data arrives.  The <tt>settimeout</tt> function defines
 a limit on the amount of time the functions can block. When a timeout is
 set and the specified amount of time has elapsed, the affected methods
-give up and fail with an error code.  
+give up and fail with an error code.
 </p>
 
 <p class="parameters">
@@ -514,6 +463,114 @@ all other method names already contained verbs making their
 imperative nature obvious.
 </p>
 
+<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class="name" id="socket.udp">
+socket.<b>udp()</b>
+</p>
+
+<p class="description">
+Creates and returns an unconnected UDP object.
+Unconnected objects support the
+<a href="#sendto"><tt>sendto</tt></a>,
+<a href="#receive"><tt>receive</tt></a>,
+<a href="#receivefrom"><tt>receivefrom</tt></a>,
+<a href="#getoption"><tt>getoption</tt></a>,
+<a href="#getsockname"><tt>getsockname</tt></a>,
+<a href="#setoption"><tt>setoption</tt></a>,
+<a href="#settimeout"><tt>settimeout</tt></a>,
+<a href="#setpeername"><tt>setpeername</tt></a>,
+<a href="#setsockname"><tt>setsockname</tt></a>, and
+<a href="#close"><tt>close</tt></a>.
+The <a href="#setpeername"><tt>setpeername</tt></a>
+is used to connect the object.
+</p>
+
+<p class="return">
+In case of success, a new unconnected UDP object
+returned. In case of error, <b><tt>nil</tt></b> is returned, followed by
+an error message.
+</p>
+
+<p class=note>
+Note: The choice between IPv4 and IPv6 happens during a call to
+<a href=#sendto><tt>sendto</tt></a>, <a
+href=#setpeername><tt>setpeername</tt></a>, or <a
+href=#setsockname><tt>sockname</tt></a>, depending on the address
+family obtained from the resolver.
+</p>
+
+<p class=note>
+Note: Before the choice between IPv4 and IPv6 happens,
+the internal socket object is invalid and therefore <a
+href=#setoption><tt>setoption</tt></a> will fail.
+</p>
+
+<!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class="name" id="socket.udp">
+socket.<b>udp4()</b>
+</p>
+
+<p class="description">
+Creates and returns an unconnected IPv4 UDP object.
+Unconnected objects support the
+<a href="#sendto"><tt>sendto</tt></a>,
+<a href="#receive"><tt>receive</tt></a>,
+<a href="#receivefrom"><tt>receivefrom</tt></a>,
+<a href="#getoption"><tt>getoption</tt></a>,
+<a href="#getsockname"><tt>getsockname</tt></a>,
+<a href="#setoption"><tt>setoption</tt></a>,
+<a href="#settimeout"><tt>settimeout</tt></a>,
+<a href="#setpeername"><tt>setpeername</tt></a>,
+<a href="#setsockname"><tt>setsockname</tt></a>, and
+<a href="#close"><tt>close</tt></a>.
+The <a href="#setpeername"><tt>setpeername</tt></a>
+is used to connect the object.
+</p>
+
+<p class="return">
+In case of success, a new unconnected UDP object
+returned. In case of error, <b><tt>nil</tt></b> is returned, followed by
+an error message.
+</p>
+
+<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<p class="name" id="socket.udp6">
+socket.<b>udp6()</b>
+</p>
+
+<p class="description">
+Creates and returns an unconnected IPv6 UDP object.
+Unconnected objects support the
+<a href="#sendto"><tt>sendto</tt></a>,
+<a href="#receive"><tt>receive</tt></a>,
+<a href="#receivefrom"><tt>receivefrom</tt></a>,
+<a href="#getoption"><tt>getoption</tt></a>,
+<a href="#getsockname"><tt>getsockname</tt></a>,
+<a href="#setoption"><tt>setoption</tt></a>,
+<a href="#settimeout"><tt>settimeout</tt></a>,
+<a href="#setpeername"><tt>setpeername</tt></a>,
+<a href="#setsockname"><tt>setsockname</tt></a>, and
+<a href="#close"><tt>close</tt></a>.
+The <a href="#setpeername"><tt>setpeername</tt></a>
+is used to connect the object.
+</p>
+
+<p class="return">
+In case of success, a new unconnected UDP object
+returned. In case of error, <b><tt>nil</tt></b> is returned, followed by
+an error message.
+</p>
+
+<p class=note>
+Note: The TCP object returned will have the option
+"<tt>ipv6-v6only</tt>" set to <tt><b>true</b></tt>.
+</p>
+
+
+
 <!-- footer ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
 
 <div class=footer>
@@ -524,7 +581,7 @@ imperative nature obvious.
 <a href="index.html#download">download</a> &middot;
 <a href="installation.html">installation</a> &middot;
 <a href="introduction.html">introduction</a> &middot;
-<a href="reference.html">reference</a> 
+<a href="reference.html">reference</a>
 </p>
 <p>
 <small>
diff --git a/etc/dispatch.lua b/etc/dispatch.lua
index cab7f59..2485415 100644
--- a/etc/dispatch.lua
+++ b/etc/dispatch.lua
@@ -5,6 +5,7 @@
 -----------------------------------------------------------------------------
 local base = _G
 local table = require("table")
+local string = require("string")
 local socket = require("socket")
 local coroutine = require("coroutine")
 module("dispatch")
@@ -43,26 +44,32 @@ end
 -----------------------------------------------------------------------------
 -- Mega hack. Don't try to do this at home.
 -----------------------------------------------------------------------------
--- we can't yield across calls to protect, so we rewrite it with coxpcall
+-- we can't yield across calls to protect on Lua 5.1, so we rewrite it with
+-- coroutines
 -- make sure you don't require any module that uses socket.protect before
 -- loading our hack
-function socket.protect(f)
-  return function(...)
-    local co = coroutine.create(f)
-    while true do
-      local results = {coroutine.resume(co, ...)}
-      local status = table.remove(results, 1)
-      if not status then
-        if base.type(results[1]) == 'table' then
-          return nil, results[1][1]
-        else base.error(results[1]) end
-      end
-      if coroutine.status(co) == "suspended" then
-        arg = {coroutine.yield(base.unpack(results))}
+if string.sub(base._VERSION, -3) == "5.1" then
+  local function _protect(co, status, ...)
+    if not status then
+      local msg = ...
+      if base.type(msg) == 'table' then
+        return nil, msg[1]
       else
-        return base.unpack(results)
+        base.error(msg, 0)
       end
     end
+    if coroutine.status(co) == "suspended" then
+      return _protect(co, coroutine.resume(co, coroutine.yield(...)))
+    else
+      return ...
+    end
+  end
+
+  function socket.protect(f)
+    return function(...)
+      local co = coroutine.create(f)
+      return _protect(co, coroutine.resume(co, ...))
+    end
   end
 end
 
diff --git a/linux.cmd b/linux.cmd
index bd59adc..6c6636b 100644
--- a/linux.cmd
+++ b/linux.cmd
@@ -1 +1 @@
-make PLAT=linux DEBUG=DEBUG LUAINC_linux_base=/home/diego/build/linux/include LUAPREFIX_linux=/home/diego/build/linux
+make PLAT=linux DEBUG=DEBUG LUAINC_linux_base=/home/diego/build/ubuntu/include LUAPREFIX_linux=/home/diego/build/ubuntu
diff --git a/luasocket-scm-0.rockspec b/luasocket-scm-0.rockspec
index f86567b..352a497 100644
--- a/luasocket-scm-0.rockspec
+++ b/luasocket-scm-0.rockspec
@@ -50,13 +50,12 @@ local function make_plat(plat)
 	}
 	local modules = {
 		["socket.core"] = {
-			sources = { "src/luasocket.c", "src/timeout.c", "src/buffer.c", "src/io.c", "src/auxiliar.c",
-						"src/options.c", "src/inet.c", "src/except.c", "src/select.c", "src/tcp.c", "src/udp.c" },
+			sources = { "src/luasocket.c", "src/timeout.c", "src/buffer.c", "src/io.c", "src/auxiliar.c", "src/options.c", "src/inet.c", "src/except.c", "src/select.c", "src/tcp.c", "src/udp.c", "src/compat.c" },
 			defines = defines[plat],
 			incdir = "/src"
 		},
-		["mime.core"] = { 
-			sources = { "src/mime.c" },
+		["mime.core"] = {
+			sources = { "src/mime.c", "src/compat.c" },
 			defines = defines[plat],
 			incdir = "/src"
 		},
@@ -73,14 +72,12 @@ local function make_plat(plat)
 	if plat == "unix" or plat == "macosx" then
 	    modules["socket.core"].sources[#modules["socket.core"].sources+1] = "src/usocket.c"
 		modules["socket.unix"] = {
-		  sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c", 
-					  "src/usocket.c", "src/unix.c" },
+		  sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c", "src/usocket.c", "src/unix.c" },
 		  defines = defines[plat],
 		  incdir = "/src"
 		}
 		modules["socket.serial"] = {
-		  sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c",
-					  "src/io.c", "src/usocket.c", "src/serial.c" },
+		  sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c", "src/usocket.c", "src/serial.c" },
 		  defines = defines[plat],
 		  incdir = "/src"
 		}
diff --git a/makefile b/makefile
index 04cd894..cc15b4e 100644
--- a/makefile
+++ b/makefile
@@ -5,12 +5,12 @@
 # Targets:
 #   install            install system independent support
 #   install-unix           also install unix-only support
-#   install-both       install for both lua5.1 and lua5.2 
-#   install-both-unix      also install unix-only 
+#   install-both       install for lua51 lua52 lua53
+#   install-both-unix      also install unix-only
 #   print	           print the build settings
 
 PLAT?= linux
-PLATS= macosx linux win32 mingw
+PLATS= macosx linux win32 mingw freebsd solaris
 
 all: $(PLAT)
 
@@ -24,20 +24,26 @@ test:
 	lua test/hello.lua
 
 install-both:
-	$(MAKE) clean 
+	$(MAKE) clean
 	@cd src; $(MAKE) $(PLAT) LUAV=5.1
 	@cd src; $(MAKE) install LUAV=5.1
-	$(MAKE) clean 
+	$(MAKE) clean
 	@cd src; $(MAKE) $(PLAT) LUAV=5.2
 	@cd src; $(MAKE) install LUAV=5.2
+	$(MAKE) clean
+	@cd src; $(MAKE) $(PLAT) LUAV=5.3
+	@cd src; $(MAKE) install LUAV=5.3
 
 install-both-unix:
-	$(MAKE) clean 
+	$(MAKE) clean
 	@cd src; $(MAKE) $(PLAT) LUAV=5.1
 	@cd src; $(MAKE) install-unix LUAV=5.1
-	$(MAKE) clean 
+	$(MAKE) clean
 	@cd src; $(MAKE) $(PLAT) LUAV=5.2
 	@cd src; $(MAKE) install-unix LUAV=5.2
+	$(MAKE) clean
+	@cd src; $(MAKE) $(PLAT) LUAV=5.3
+	@cd src; $(MAKE) install-unix LUAV=5.3
 
 .PHONY: test
 
diff --git a/src/auxiliar.c b/src/auxiliar.c
index de625e9..18fa8e4 100644
--- a/src/auxiliar.c
+++ b/src/auxiliar.c
@@ -26,7 +26,7 @@ void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) {
     luaL_newmetatable(L, classname); /* mt */
     /* create __index table to place methods */
     lua_pushstring(L, "__index");    /* mt,"__index" */
-    lua_newtable(L);                 /* mt,"__index",it */ 
+    lua_newtable(L);                 /* mt,"__index",it */
     /* put class name into class metatable */
     lua_pushstring(L, "class");      /* mt,"__index",it,"class" */
     lua_pushstring(L, classname);    /* mt,"__index",it,"class",classname */
@@ -84,7 +84,7 @@ int auxiliar_checkboolean(lua_State *L, int objidx) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Return userdata pointer if object belongs to a given class, abort with 
+* Return userdata pointer if object belongs to a given class, abort with
 * error otherwise
 \*-------------------------------------------------------------------------*/
 void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) {
@@ -98,7 +98,7 @@ void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Return userdata pointer if object belongs to a given group, abort with 
+* Return userdata pointer if object belongs to a given group, abort with
 * error otherwise
 \*-------------------------------------------------------------------------*/
 void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) {
@@ -121,7 +121,7 @@ void auxiliar_setclass(lua_State *L, const char *classname, int objidx) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Get a userdata pointer if object belongs to a given group. Return NULL 
+* Get a userdata pointer if object belongs to a given group. Return NULL
 * otherwise
 \*-------------------------------------------------------------------------*/
 void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) {
@@ -139,7 +139,7 @@ void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Get a userdata pointer if object belongs to a given class. Return NULL 
+* Get a userdata pointer if object belongs to a given class. Return NULL
 * otherwise
 \*-------------------------------------------------------------------------*/
 void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) {
@@ -151,7 +151,7 @@ void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) {
 * Used to be part of lauxlib in Lua 5.1, was dropped from 5.2.
 \*-------------------------------------------------------------------------*/
 int auxiliar_typeerror (lua_State *L, int narg, const char *tname) {
-  const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, 
+  const char *msg = lua_pushfstring(L, "%s expected, got %s", tname,
       luaL_typename(L, narg));
   return luaL_argerror(L, narg, msg);
 }
diff --git a/src/auxiliar.h b/src/auxiliar.h
index ea99013..65511d4 100644
--- a/src/auxiliar.h
+++ b/src/auxiliar.h
@@ -4,12 +4,12 @@
 * Auxiliar routines for class hierarchy manipulation
 * LuaSocket toolkit (but completely independent of other LuaSocket modules)
 *
-* A LuaSocket class is a name associated with Lua metatables. A LuaSocket 
-* group is a name associated with a class. A class can belong to any number 
+* A LuaSocket class is a name associated with Lua metatables. A LuaSocket
+* group is a name associated with a class. A class can belong to any number
 * of groups. This module provides the functionality to:
 *
-*   - create new classes 
-*   - add classes to groups 
+*   - create new classes
+*   - add classes to groups
 *   - set the class of objects
 *   - check if an object belongs to a given class or group
 *   - get the userdata associated to objects
@@ -26,11 +26,12 @@
 * "class" with the class name.
 *
 * The mapping from class name to the corresponding metatable and the
-* reverse mapping are done using lauxlib. 
+* reverse mapping are done using lauxlib.
 \*=========================================================================*/
 
 #include "lua.h"
 #include "lauxlib.h"
+#include "compat.h"
 
 int auxiliar_open(lua_State *L);
 void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func);
diff --git a/src/buffer.c b/src/buffer.c
index 4ef4e8e..fff1634 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -4,6 +4,7 @@
 \*=========================================================================*/
 #include "lua.h"
 #include "lauxlib.h"
+#include "compat.h"
 
 #include "buffer.h"
 
@@ -37,7 +38,7 @@ int buffer_open(lua_State *L) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Initializes C structure 
+* Initializes C structure
 \*-------------------------------------------------------------------------*/
 void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
     buf->first = buf->last = 0;
@@ -61,8 +62,8 @@ int buffer_meth_getstats(lua_State *L, p_buffer buf) {
 * object:setstats() interface
 \*-------------------------------------------------------------------------*/
 int buffer_meth_setstats(lua_State *L, p_buffer buf) {
-    buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); 
-    buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); 
+    buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received);
+    buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent);
     if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4);
     lua_pushnumber(L, 1);
     return 1;
@@ -78,9 +79,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
     const char *data = luaL_checklstring(L, 2, &size);
     long start = (long) luaL_optnumber(L, 3, 1);
     long end = (long) luaL_optnumber(L, 4, -1);
-#ifdef LUASOCKET_DEBUG
-    p_timeout tm = timeout_markstart(buf->tm);
-#endif
+    timeout_markstart(buf->tm);
     if (start < 0) start = (long) (size+start+1);
     if (end < 0) end = (long) (size+end+1);
     if (start < 1) start = (long) 1;
@@ -89,7 +88,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
     /* check if there was an error */
     if (err != IO_DONE) {
         lua_pushnil(L);
-        lua_pushstring(L, buf->io->error(buf->io->ctx, err)); 
+        lua_pushstring(L, buf->io->error(buf->io->ctx, err));
         lua_pushnumber(L, (lua_Number) (sent+start-1));
     } else {
         lua_pushnumber(L, (lua_Number) (sent+start-1));
@@ -98,7 +97,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
     }
 #ifdef LUASOCKET_DEBUG
     /* push time elapsed during operation as the last return value */
-    lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm));
+    lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
 #endif
     return lua_gettop(L) - top;
 }
@@ -111,10 +110,8 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
     luaL_Buffer b;
     size_t size;
     const char *part = luaL_optlstring(L, 3, "", &size);
-#ifdef LUASOCKET_DEBUG
-    p_timeout tm = timeout_markstart(buf->tm);
-#endif
-    /* initialize buffer with optional extra prefix 
+    timeout_markstart(buf->tm);
+    /* initialize buffer with optional extra prefix
      * (useful for concatenating previous partial results) */
     luaL_buffinit(L, &b);
     luaL_addlstring(&b, part, size);
@@ -122,12 +119,12 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
     if (!lua_isnumber(L, 2)) {
         const char *p= luaL_optstring(L, 2, "*l");
         if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
-        else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); 
+        else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
         else luaL_argcheck(L, 0, 2, "invalid receive pattern");
-    /* get a fixed number of bytes (minus what was already partially 
+    /* get a fixed number of bytes (minus what was already partially
      * received) */
     } else {
-        double n = lua_tonumber(L, 2); 
+        double n = lua_tonumber(L, 2);
         size_t wanted = (size_t) n;
         luaL_argcheck(L, n >= 0, 2, "invalid receive pattern");
         if (size == 0 || wanted > size)
@@ -138,8 +135,8 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
         /* we can't push anyting in the stack before pushing the
          * contents of the buffer. this is the reason for the complication */
         luaL_pushresult(&b);
-        lua_pushstring(L, buf->io->error(buf->io->ctx, err)); 
-        lua_pushvalue(L, -2); 
+        lua_pushstring(L, buf->io->error(buf->io->ctx, err));
+        lua_pushvalue(L, -2);
         lua_pushnil(L);
         lua_replace(L, -4);
     } else {
@@ -149,7 +146,7 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
     }
 #ifdef LUASOCKET_DEBUG
     /* push time elapsed during operation as the last return value */
-    lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm));
+    lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
 #endif
     return lua_gettop(L) - top;
 }
@@ -222,7 +219,7 @@ static int recvall(p_buffer buf, luaL_Buffer *b) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF 
+* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
 * are not returned by the function and are discarded from the buffer
 \*-------------------------------------------------------------------------*/
 static int recvline(p_buffer buf, luaL_Buffer *b) {
@@ -252,7 +249,7 @@ static int recvline(p_buffer buf, luaL_Buffer *b) {
 static void buffer_skip(p_buffer buf, size_t count) {
     buf->received += count;
     buf->first += count;
-    if (buffer_isempty(buf)) 
+    if (buffer_isempty(buf))
         buf->first = buf->last = 0;
 }
 
diff --git a/src/compat.c b/src/compat.c
new file mode 100644
index 0000000..c2d99cb
--- /dev/null
+++ b/src/compat.c
@@ -0,0 +1,19 @@
+#include "compat.h"
+
+#if LUA_VERSION_NUM==501
+/*
+** Adapted from Lua 5.2
+*/
+void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+  luaL_checkstack(L, nup+1, "too many upvalues");
+  for (; l->name != NULL; l++) {  /* fill the table with given functions */
+    int i;
+    lua_pushstring(L, l->name);
+    for (i = 0; i < nup; i++)  /* copy upvalues to the top */
+      lua_pushvalue(L, -(nup+1));
+    lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
+    lua_settable(L, -(nup + 3));
+  }
+  lua_pop(L, nup);  /* remove upvalues */
+}
+#endif
diff --git a/src/compat.h b/src/compat.h
new file mode 100644
index 0000000..7bf8010
--- /dev/null
+++ b/src/compat.h
@@ -0,0 +1,11 @@
+#ifndef COMPAT_H
+#define COMPAT_H
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#if LUA_VERSION_NUM==501
+void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
+#endif
+
+#endif
diff --git a/src/except.c b/src/except.c
index 002e701..60b5005 100644
--- a/src/except.c
+++ b/src/except.c
@@ -6,9 +6,19 @@
 
 #include "lua.h"
 #include "lauxlib.h"
+#include "compat.h"
 
 #include "except.h"
 
+#if LUA_VERSION_NUM < 502
+#define lua_pcallk(L, na, nr, err, ctx, cont) \
+    (((void)ctx),((void)cont),lua_pcall(L, na, nr, err))
+#endif
+
+#if LUA_VERSION_NUM < 503
+typedef int lua_KContext;
+#endif
+
 /*=========================================================================*\
 * Internal function prototypes.
 \*=========================================================================*/
@@ -29,18 +39,17 @@ static luaL_Reg func[] = {
 * Try factory
 \*-------------------------------------------------------------------------*/
 static void wrap(lua_State *L) {
-    lua_newtable(L);
-    lua_pushnumber(L, 1);
-    lua_pushvalue(L, -3);
-    lua_settable(L, -3);
-    lua_insert(L, -2);
-    lua_pop(L, 1);
+    lua_createtable(L, 1, 0);
+    lua_pushvalue(L, -2);
+    lua_rawseti(L, -2, 1);
+    lua_pushvalue(L, lua_upvalueindex(1));
+    lua_setmetatable(L, -2);
 }
 
 static int finalize(lua_State *L) {
     if (!lua_toboolean(L, 1)) {
-        lua_pushvalue(L, lua_upvalueindex(1));
-        lua_pcall(L, 0, 0, 0);
+        lua_pushvalue(L, lua_upvalueindex(2));
+        lua_call(L, 0, 0);
         lua_settop(L, 2);
         wrap(L);
         lua_error(L);
@@ -48,15 +57,17 @@ static int finalize(lua_State *L) {
     } else return lua_gettop(L);
 }
 
-static int do_nothing(lua_State *L) { 
+static int do_nothing(lua_State *L) {
     (void) L;
-    return 0; 
+    return 0;
 }
 
 static int global_newtry(lua_State *L) {
     lua_settop(L, 1);
     if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing);
-    lua_pushcclosure(L, finalize, 1);
+    lua_pushvalue(L, lua_upvalueindex(1));
+    lua_insert(L, -2);
+    lua_pushcclosure(L, finalize, 2);
     return 1;
 }
 
@@ -64,27 +75,49 @@ static int global_newtry(lua_State *L) {
 * Protect factory
 \*-------------------------------------------------------------------------*/
 static int unwrap(lua_State *L) {
-    if (lua_istable(L, -1)) {
-        lua_pushnumber(L, 1);
-        lua_gettable(L, -2);
-        lua_pushnil(L);
-        lua_insert(L, -2);
-        return 1;
-    } else return 0;
+    if (lua_istable(L, -1) && lua_getmetatable(L, -1)) {
+        int r = lua_rawequal(L, -1, lua_upvalueindex(1));
+        lua_pop(L, 1);
+        if (r) {
+            lua_pushnil(L);
+            lua_rawgeti(L, -2, 1);
+            return 1;
+        }
+    }
+    return 0;
 }
 
-static int protected_(lua_State *L) {
-    lua_pushvalue(L, lua_upvalueindex(1));
-    lua_insert(L, 1);
-    if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) {
+static int protected_finish(lua_State *L, int status, lua_KContext ctx) {
+    (void)ctx;
+    if (status != 0 && status != LUA_YIELD) {
         if (unwrap(L)) return 2;
-        else lua_error(L);
-        return 0;
+        else return lua_error(L);
     } else return lua_gettop(L);
 }
 
+#if LUA_VERSION_NUM == 502
+static int protected_cont(lua_State *L) {
+    int ctx = 0;
+    int status = lua_getctx(L, &ctx);
+    return protected_finish(L, status, ctx);
+}
+#else
+#define protected_cont protected_finish
+#endif
+
+static int protected_(lua_State *L) {
+    int status;
+    lua_pushvalue(L, lua_upvalueindex(2));
+    lua_insert(L, 1);
+    status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont);
+    return protected_finish(L, status, 0);
+}
+
 static int global_protect(lua_State *L) {
-    lua_pushcclosure(L, protected_, 1);
+    lua_settop(L, 1);
+    lua_pushvalue(L, lua_upvalueindex(1));
+    lua_insert(L, 1);
+    lua_pushcclosure(L, protected_, 2);
     return 1;
 }
 
@@ -92,10 +125,9 @@ static int global_protect(lua_State *L) {
 * Init module
 \*-------------------------------------------------------------------------*/
 int except_open(lua_State *L) {
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
-    luaL_setfuncs(L, func, 0);
-#else
-    luaL_openlib(L, NULL, func, 0);
-#endif
+    lua_newtable(L); /* metatable for wrapped exceptions */
+    lua_pushboolean(L, 0);
+    lua_setfield(L, -2, "__metatable");
+    luaL_setfuncs(L, func, 1);
     return 0;
 }
diff --git a/src/except.h b/src/except.h
index 1e7a245..2497c05 100644
--- a/src/except.h
+++ b/src/except.h
@@ -9,21 +9,26 @@
 * error checking was taking a substantial amount of the coding. These
 * function greatly simplify the task of checking errors.
 *
-* The main idea is that functions should return nil as its first return
-* value when it finds an error, and return an error message (or value)
+* The main idea is that functions should return nil as their first return
+* values when they find an error, and return an error message (or value)
 * following nil. In case of success, as long as the first value is not nil,
 * the other values don't matter.
 *
 * The idea is to nest function calls with the "try" function. This function
-* checks the first value, and calls "error" on the second if the first is
-* nil. Otherwise, it returns all values it received. 
+* checks the first value, and, if it's falsy, wraps the second value in a
+* table with metatable and calls "error" on it. Otherwise, it returns all
+* values it received. Basically, it works like the Lua "assert" function,
+* but it creates errors targeted specifically at "protect".
 *
-* The protect function returns a new function that behaves exactly like the
-* function it receives, but the new function doesn't throw exceptions: it
-* returns nil followed by the error message instead.
+* The "newtry" function is a factory for "try" functions that call a
+* finalizer in protected mode before calling "error".
 *
-* With these two function, it's easy to write functions that throw
-* exceptions on error, but that don't interrupt the user script. 
+* The "protect" function returns a new function that behaves exactly like
+* the function it receives, but the new function catches exceptions thrown
+* by "try" functions and returns nil followed by the error message instead.
+*
+* With these three functions, it's easy to write functions that throw
+* exceptions on error, but that don't interrupt the user script.
 \*=========================================================================*/
 
 #include "lua.h"
diff --git a/src/ftp.lua b/src/ftp.lua
index ea1145b..e0c3cae 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -268,11 +268,20 @@ _M.command = socket.protect(function(cmdt)
     cmdt = override(cmdt)
     socket.try(cmdt.host, "missing hostname")
     socket.try(cmdt.command, "missing command")
-    local f = open(cmdt.host, cmdt.port, cmdt.create)
+    local f = _M.open(cmdt.host, cmdt.port, cmdt.create)
     f:greet()
     f:login(cmdt.user, cmdt.password)
-    f.try(f.tp:command(cmdt.command, cmdt.argument))
-    if cmdt.check then f.try(f.tp:check(cmdt.check)) end
+    if type(cmdt.command) == "table" then
+        local argument = cmdt.argument or {}
+        local check = cmdt.check or {}
+        for i,cmd in ipairs(cmdt.command) do
+            f.try(f.tp:command(cmd, argument[i]))
+            if check[i] then f.try(f.tp:check(check[i])) end
+        end
+    else
+        f.try(f.tp:command(cmdt.command, cmdt.argument))
+        if cmdt.check then f.try(f.tp:check(cmdt.check)) end
+    end
     f:quit()
     return f:close()
 end)
@@ -282,4 +291,4 @@ _M.get = socket.protect(function(gett)
     else return tget(gett) end
 end)
 
-return _M
\ No newline at end of file
+return _M
diff --git a/src/http.lua b/src/http.lua
index ac4b2d6..d6bcc91 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -22,12 +22,15 @@ local _M = socket.http
 -- Program constants
 -----------------------------------------------------------------------------
 -- connection timeout in seconds
-TIMEOUT = 60
--- default port for document retrieval
-_M.PORT = 80
+_M.TIMEOUT = 60
 -- user agent field sent in request
 _M.USERAGENT = socket._VERSION
 
+-- supported schemes
+local SCHEMES = { ["http"] = true }
+-- default port for document retrieval
+local PORT = 80
+
 -----------------------------------------------------------------------------
 -- Reads MIME headers from a connection, unfolding where needed
 -----------------------------------------------------------------------------
@@ -114,7 +117,7 @@ function _M.open(host, port, create)
     h.try = socket.newtry(function() h:close() end)
     -- set timeout before connecting
     h.try(c:settimeout(_M.TIMEOUT))
-    h.try(c:connect(host, port or _M.PORT))
+    h.try(c:connect(host, port or PORT))
     -- here everything worked
     return h
 end
@@ -186,7 +189,7 @@ end
 local function adjusturi(reqt)
     local u = reqt
     -- if there is a proxy, we need the full url. otherwise, just a part.
-    if not reqt.proxy and not PROXY then
+    if not reqt.proxy and not _M.PROXY then
         u = {
            path = socket.try(reqt.path, "invalid path 'nil'"),
            params = reqt.params,
@@ -198,7 +201,7 @@ local function adjusturi(reqt)
 end
 
 local function adjustproxy(reqt)
-    local proxy = reqt.proxy or PROXY
+    local proxy = reqt.proxy or _M.PROXY
     if proxy then
         proxy = url.parse(proxy)
         return proxy.host, proxy.port or 3128
@@ -209,17 +212,27 @@ end
 
 local function adjustheaders(reqt)
     -- default headers
+    local host = string.gsub(reqt.authority, "^.-@", "")
     local lower = {
         ["user-agent"] = _M.USERAGENT,
-        ["host"] = reqt.host,
+        ["host"] = host,
         ["connection"] = "close, TE",
         ["te"] = "trailers"
     }
     -- if we have authentication information, pass it along
     if reqt.user and reqt.password then
-        lower["authorization"] = 
+        lower["authorization"] =
             "Basic " ..  (mime.b64(reqt.user .. ":" .. reqt.password))
     end
+    -- if we have proxy authentication information, pass it along
+    local proxy = reqt.proxy or _M.PROXY
+    if proxy then
+        proxy = url.parse(proxy)
+        if proxy.user and proxy.password then
+            lower["proxy-authorization"] =
+                "Basic " ..  (mime.b64(proxy.user .. ":" .. proxy.password))
+        end
+    end
     -- override with user headers
     for i,v in base.pairs(reqt.headers or lower) do
         lower[string.lower(i)] = v
@@ -230,7 +243,7 @@ end
 -- default url parts
 local default = {
     host = "",
-    port = _M.PORT,
+    port = PORT,
     path ="/",
     scheme = "http"
 }
@@ -240,22 +253,27 @@ local function adjustrequest(reqt)
     local nreqt = reqt.url and url.parse(reqt.url, default) or {}
     -- explicit components override url
     for i,v in base.pairs(reqt) do nreqt[i] = v end
-    if nreqt.port == "" then nreqt.port = 80 end
-    socket.try(nreqt.host and nreqt.host ~= "", 
-        "invalid host '" .. base.tostring(nreqt.host) .. "'")
+    if nreqt.port == "" then nreqt.port = PORT end
+    if not (nreqt.host and nreqt.host ~= "") then
+        socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'")
+    end
     -- compute uri if user hasn't overriden
     nreqt.uri = reqt.uri or adjusturi(nreqt)
-    -- ajust host and port if there is a proxy
-    nreqt.host, nreqt.port = adjustproxy(nreqt)
     -- adjust headers in request
     nreqt.headers = adjustheaders(nreqt)
+    -- ajust host and port if there is a proxy
+    nreqt.host, nreqt.port = adjustproxy(nreqt)
     return nreqt
 end
 
 local function shouldredirect(reqt, code, headers)
-    return headers.location and
-           string.gsub(headers.location, "%s", "") ~= "" and
-           (reqt.redirect ~= false) and
+    local location = headers.location
+    if not location then return false end
+    location = string.gsub(location, "%s", "")
+    if location == "" then return false end
+    local scheme = string.match(location, "^([%w][%w%+%-%.]*)%:")
+    if scheme and not SCHEMES[scheme] then return false end
+    return (reqt.redirect ~= false) and
            (code == 301 or code == 302 or code == 303 or code == 307) and
            (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
            and (not reqt.nredirects or reqt.nredirects < 5)
@@ -279,10 +297,10 @@ local trequest, tredirect
         source = reqt.source,
         sink = reqt.sink,
         headers = reqt.headers,
-        proxy = reqt.proxy, 
+        proxy = reqt.proxy,
         nredirects = (reqt.nredirects or 0) + 1,
         create = reqt.create
-    }   
+    }
     -- pass location header back as a hint we redirected
     headers = headers or {}
     headers.location = headers.location or location
@@ -299,7 +317,7 @@ end
     h:sendheaders(nreqt.headers)
     -- if there is a body, send it
     if nreqt.source then
-        h:sendbody(nreqt.headers, nreqt.source, nreqt.step) 
+        h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
     end
     local code, status = h:receivestatusline()
     -- if it is an HTTP/0.9 server, simply get the body and we are done
@@ -309,13 +327,13 @@ end
     end
     local headers
     -- ignore any 100-continue messages
-    while code == 100 do 
+    while code == 100 do
         headers = h:receiveheaders()
         code, status = h:receivestatusline()
     end
     headers = h:receiveheaders()
     -- at this point we should have a honest reply from the server
-    -- we can't redirect if we already used the source, so we report the error 
+    -- we can't redirect if we already used the source, so we report the error
     if shouldredirect(nreqt, code, headers) and not nreqt.source then
         h:close()
         return tredirect(reqt, headers.location)
@@ -351,4 +369,4 @@ _M.request = socket.protect(function(reqt, body)
     else return trequest(reqt) end
 end)
 
-return _M
\ No newline at end of file
+return _M
diff --git a/src/inet.c b/src/inet.c
index 1a411f6..f4c8404 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -8,6 +8,7 @@
 
 #include "lua.h"
 #include "lauxlib.h"
+#include "compat.h"
 
 #include "inet.h"
 
@@ -41,11 +42,7 @@ int inet_open(lua_State *L)
 {
     lua_pushstring(L, "dns");
     lua_newtable(L);
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
     luaL_setfuncs(L, func, 0);
-#else
-    luaL_openlib(L, NULL, func, 0);
-#endif
     lua_settable(L, -3);
     return 0;
 }
@@ -97,7 +94,7 @@ static int inet_global_getnameinfo(lua_State *L) {
 
     memset(&hints, 0, sizeof(hints));
     hints.ai_socktype = SOCK_STREAM;
-    hints.ai_family = PF_UNSPEC;
+    hints.ai_family = AF_UNSPEC;
 
     ret = getaddrinfo(host, serv, &hints, &resolved);
     if (ret != 0) {
@@ -108,8 +105,8 @@ static int inet_global_getnameinfo(lua_State *L) {
 
     lua_newtable(L);
     for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) {
-        getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, 
-            hbuf, host? (socklen_t) sizeof(hbuf): 0, 
+        getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen,
+            hbuf, host? (socklen_t) sizeof(hbuf): 0,
             sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0);
         if (host) {
             lua_pushnumber(L, i);
@@ -149,7 +146,7 @@ static int inet_global_toip(lua_State *L)
 int inet_optfamily(lua_State* L, int narg, const char* def)
 {
     static const char* optname[] = { "unspec", "inet", "inet6", NULL };
-    static int optvalue[] = { PF_UNSPEC, PF_INET, PF_INET6, 0 };
+    static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 };
 
     return optvalue[luaL_checkoption(L, narg, def, optname)];
 }
@@ -170,7 +167,7 @@ static int inet_global_getaddrinfo(lua_State *L)
     int i = 1, ret = 0;
     memset(&hints, 0, sizeof(hints));
     hints.ai_socktype = SOCK_STREAM;
-    hints.ai_family = PF_UNSPEC;
+    hints.ai_family = AF_UNSPEC;
     ret = getaddrinfo(hostname, NULL, &hints, &resolved);
     if (ret != 0) {
         lua_pushnil(L);
@@ -180,9 +177,10 @@ static int inet_global_getaddrinfo(lua_State *L)
     lua_newtable(L);
     for (iterator = resolved; iterator; iterator = iterator->ai_next) {
         char hbuf[NI_MAXHOST];
-        ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, 
+        ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen,
             hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
         if (ret){
+          freeaddrinfo(resolved);
           lua_pushnil(L);
           lua_pushstring(L, socket_gaistrerror(ret));
           return 2;
@@ -200,6 +198,16 @@ static int inet_global_getaddrinfo(lua_State *L)
                 lua_pushliteral(L, "inet6");
                 lua_settable(L, -3);
                 break;
+            case AF_UNSPEC:
+                lua_pushliteral(L, "family");
+                lua_pushliteral(L, "unspec");
+                lua_settable(L, -3);
+                break;
+            default:
+                lua_pushliteral(L, "family");
+                lua_pushliteral(L, "unknown");
+                lua_settable(L, -3);
+                break;
         }
         lua_pushliteral(L, "addr");
         lua_pushstring(L, hbuf);
@@ -256,12 +264,11 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family)
     }
     lua_pushstring(L, name);
     lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10));
-    if (family == PF_INET) {
-        lua_pushliteral(L, "inet");
-    } else if (family == PF_INET6) {
-        lua_pushliteral(L, "inet6");
-    } else {
-        lua_pushliteral(L, "uknown family");
+    switch (family) {
+        case AF_INET: lua_pushliteral(L, "inet"); break;
+        case AF_INET6: lua_pushliteral(L, "inet6"); break;
+        case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
+        default: lua_pushliteral(L, "unknown"); break;
     }
     return 3;
 }
@@ -281,7 +288,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
         lua_pushstring(L, socket_strerror(errno));
         return 2;
     }
-	err=getnameinfo((struct sockaddr *)&peer, peer_len, 
+	err=getnameinfo((struct sockaddr *)&peer, peer_len,
 		name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV);
     if (err) {
         lua_pushnil(L);
@@ -290,12 +297,11 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
     }
     lua_pushstring(L, name);
     lua_pushstring(L, port);
-    if (family == PF_INET) {
-        lua_pushliteral(L, "inet");
-    } else if (family == PF_INET6) {
-        lua_pushliteral(L, "inet6");
-    } else {
-        lua_pushliteral(L, "uknown family");
+    switch (family) {
+        case AF_INET: lua_pushliteral(L, "inet"); break;
+        case AF_INET6: lua_pushliteral(L, "inet6"); break;
+        case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
+        default: lua_pushliteral(L, "unknown"); break;
     }
     return 3;
 }
@@ -346,8 +352,13 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
 /*-------------------------------------------------------------------------*\
 * Tries to create a new inet socket
 \*-------------------------------------------------------------------------*/
-const char *inet_trycreate(p_socket ps, int family, int type) {
-    return socket_strerror(socket_create(ps, family, type, 0));
+const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
+    const char *err = socket_strerror(socket_create(ps, family, type, protocol));
+    if (err == NULL && family == AF_INET6) {
+        int yes = 1;
+        setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes));
+    }
+    return err;
 }
 
 /*-------------------------------------------------------------------------*\
@@ -356,21 +367,21 @@ const char *inet_trycreate(p_socket ps, int family, int type) {
 const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
 {
     switch (family) {
-        case PF_INET: {
+        case AF_INET: {
             struct sockaddr_in sin;
             memset((char *) &sin, 0, sizeof(sin));
             sin.sin_family = AF_UNSPEC;
             sin.sin_addr.s_addr = INADDR_ANY;
-            return socket_strerror(socket_connect(ps, (SA *) &sin, 
+            return socket_strerror(socket_connect(ps, (SA *) &sin,
                 sizeof(sin), tm));
         }
-        case PF_INET6: {
+        case AF_INET6: {
             struct sockaddr_in6 sin6;
-            struct in6_addr addrany = IN6ADDR_ANY_INIT; 
+            struct in6_addr addrany = IN6ADDR_ANY_INIT;
             memset((char *) &sin6, 0, sizeof(sin6));
             sin6.sin6_family = AF_UNSPEC;
             sin6.sin6_addr = addrany;
-            return socket_strerror(socket_connect(ps, (SA *) &sin6, 
+            return socket_strerror(socket_connect(ps, (SA *) &sin6,
                 sizeof(sin6), tm));
         }
     }
@@ -385,6 +396,7 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
 {
     struct addrinfo *iterator = NULL, *resolved = NULL;
     const char *err = NULL;
+    int current_family = *family;
     /* try resolving */
     err = socket_gaistrerror(getaddrinfo(address, serv,
                 connecthints, &resolved));
@@ -399,23 +411,23 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
          * that shows up while iterating. if there was a
          * bind, all families will be the same and we will
          * not enter this branch. */
-        if (*family != iterator->ai_family) {
+        if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
             socket_destroy(ps);
-            err = socket_strerror(socket_create(ps, iterator->ai_family, 
-                iterator->ai_socktype, iterator->ai_protocol));
-            if (err != NULL) {
-                freeaddrinfo(resolved);
-                return err;
-            }
-            *family = iterator->ai_family;
-            /* all sockets initially non-blocking */
+            err = inet_trycreate(ps, iterator->ai_family,
+                iterator->ai_socktype, iterator->ai_protocol);
+            if (err) continue;
+            current_family = iterator->ai_family;
+            /* set non-blocking before connect */
             socket_setnonblocking(ps);
         }
         /* try connecting to remote address */
-        err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, 
+        err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
             (socklen_t) iterator->ai_addrlen, tm));
-        /* if success, break out of loop */
-        if (err == NULL) break;
+        /* if success or timeout is zero, break out of loop */
+        if (err == NULL || timeout_iszero(tm)) {
+            *family = current_family;
+            break;
+        }
     }
     freeaddrinfo(resolved);
     /* here, if err is set, we failed */
@@ -425,29 +437,27 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
 /*-------------------------------------------------------------------------*\
 * Tries to accept a socket
 \*-------------------------------------------------------------------------*/
-const char *inet_tryaccept(p_socket server, int family, p_socket client, 
-    p_timeout tm)
-{
+const char *inet_tryaccept(p_socket server, int family, p_socket client,
+    p_timeout tm) {
 	socklen_t len;
 	t_sockaddr_storage addr;
-	if (family == PF_INET6) {
-		len = sizeof(struct sockaddr_in6);
-	} else {
-		len = sizeof(struct sockaddr_in);
-	}
-	return socket_strerror(socket_accept(server, client, (SA *) &addr, 
+    switch (family) {
+        case AF_INET6: len = sizeof(struct sockaddr_in6); break;
+        case AF_INET: len = sizeof(struct sockaddr_in); break;
+        default: len = sizeof(addr); break;
+    }
+	return socket_strerror(socket_accept(server, client, (SA *) &addr,
         &len, tm));
 }
 
 /*-------------------------------------------------------------------------*\
 * Tries to bind socket to (address, port)
 \*-------------------------------------------------------------------------*/
-const char *inet_trybind(p_socket ps, const char *address, const char *serv,
-        struct addrinfo *bindhints)
-{
+const char *inet_trybind(p_socket ps, int *family, const char *address,
+    const char *serv, struct addrinfo *bindhints) {
     struct addrinfo *iterator = NULL, *resolved = NULL;
     const char *err = NULL;
-    t_socket sock = *ps;
+    int current_family = *family;
     /* translate luasocket special values to C */
     if (strcmp(address, "*") == 0) address = NULL;
     if (!serv) serv = "0";
@@ -459,35 +469,32 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv,
     }
     /* iterate over resolved addresses until one is good */
     for (iterator = resolved; iterator; iterator = iterator->ai_next) {
-        if(sock == SOCKET_INVALID) {
-            err = socket_strerror(socket_create(&sock, iterator->ai_family,
-                        iterator->ai_socktype, iterator->ai_protocol));
-            if(err)
-                continue;
+        if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
+            socket_destroy(ps);
+            err = inet_trycreate(ps, iterator->ai_family,
+                        iterator->ai_socktype, iterator->ai_protocol);
+            if (err) continue;
+            current_family = iterator->ai_family;
         }
         /* try binding to local address */
-        err = socket_strerror(socket_bind(&sock,
-            (SA *) iterator->ai_addr,
+        err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr,
             (socklen_t) iterator->ai_addrlen));
-
         /* keep trying unless bind succeeded */
-        if (err) {
-            if(sock != *ps)
-                socket_destroy(&sock);
-        } else {
-            /* remember what we connected to, particularly the family */
-            *bindhints = *iterator;
+        if (err == NULL) {
+            *family = current_family;
+            /* set to non-blocking after bind */
+            socket_setnonblocking(ps);
             break;
         }
     }
     /* cleanup and return error */
     freeaddrinfo(resolved);
-    *ps = sock;
+    /* here, if err is set, we failed */
     return err;
 }
 
 /*-------------------------------------------------------------------------*\
-* Some systems do not provide these so that we provide our own. 
+* Some systems do not provide these so that we provide our own.
 \*-------------------------------------------------------------------------*/
 #ifdef LUASOCKET_INET_ATON
 int inet_aton(const char *cp, struct in_addr *inp)
@@ -512,7 +519,7 @@ int inet_aton(const char *cp, struct in_addr *inp)
 #endif
 
 #ifdef LUASOCKET_INET_PTON
-int inet_pton(int af, const char *src, void *dst) 
+int inet_pton(int af, const char *src, void *dst)
 {
     struct addrinfo hints, *res;
     int ret = 1;
@@ -529,7 +536,7 @@ int inet_pton(int af, const char *src, void *dst)
     } else {
         ret = -1;
     }
-    freeaddrinfo(res); 
+    freeaddrinfo(res);
     return ret;
 }
 
diff --git a/src/inet.h b/src/inet.h
index 1f1a96a..feb3541 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -1,12 +1,12 @@
-#ifndef INET_H 
-#define INET_H 
+#ifndef INET_H
+#define INET_H
 /*=========================================================================*\
 * Internet domain functions
 * LuaSocket toolkit
 *
 * This module implements the creation and connection of internet domain
 * sockets, on top of the socket.h interface, and the interface of with the
-* resolver. 
+* resolver.
 *
 * The function inet_aton is provided for the platforms where it is not
 * available. The module also implements the interface of the internet
@@ -24,11 +24,11 @@
 
 int inet_open(lua_State *L);
 
-const char *inet_trycreate(p_socket ps, int family, int type);
+const char *inet_trycreate(p_socket ps, int family, int type, int protocol);
 const char *inet_tryconnect(p_socket ps, int *family, const char *address,
         const char *serv, p_timeout tm, struct addrinfo *connecthints);
-const char *inet_trybind(p_socket ps, const char *address, const char *serv,
-        struct addrinfo *bindhints);
+const char *inet_trybind(p_socket ps, int *family, const char *address,
+        const char *serv, struct addrinfo *bindhints);
 const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm);
 const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm);
 
diff --git a/src/io.c b/src/io.c
index 35f46f7..a4230ce 100644
--- a/src/io.c
+++ b/src/io.c
@@ -25,6 +25,6 @@ const char *io_strerror(int err) {
         case IO_DONE: return NULL;
         case IO_CLOSED: return "closed";
         case IO_TIMEOUT: return "timeout";
-        default: return "unknown error"; 
+        default: return "unknown error";
     }
 }
diff --git a/src/io.h b/src/io.h
index 76a3e58..8cca08a 100644
--- a/src/io.h
+++ b/src/io.h
@@ -22,7 +22,7 @@ enum {
     IO_DONE = 0,        /* operation completed successfully */
     IO_TIMEOUT = -1,    /* operation timed out */
     IO_CLOSED = -2,     /* the connection has been closed */
-	IO_UNKNOWN = -3     
+	IO_UNKNOWN = -3
 };
 
 /* interface to error message function */
diff --git a/src/ltn12.lua b/src/ltn12.lua
index 5b10f56..575c5a7 100644
--- a/src/ltn12.lua
+++ b/src/ltn12.lua
@@ -9,6 +9,7 @@
 -----------------------------------------------------------------------------
 local string = require("string")
 local table = require("table")
+local unpack = unpack or table.unpack
 local base = _G
 local _M = {}
 if module then -- heuristic for exporting a global package table
@@ -21,6 +22,9 @@ _M.source = source
 _M.sink = sink
 _M.pump = pump
 
+local unpack = unpack or table.unpack
+local select = base.select
+
 -- 2048 seems to be better in windows...
 _M.BLOCKSIZE = 2048
 _M._VERSION = "LTN12 1.0.3"
@@ -42,7 +46,7 @@ end
 -- (thanks to Wim Couwenberg)
 function filter.chain(...)
     local arg = {...}
-    local n = select('#',...)
+    local n = base.select('#',...)
     local top, index = 1, 1
     local retry = ""
     return function(chunk)
@@ -139,7 +143,9 @@ function source.rewind(src)
     end
 end
 
-function source.chain(src, f)
+-- chains a source with one or several filter(s)
+function source.chain(src, f, ...)
+    if ... then f=filter.chain(f, ...) end
     base.assert(src and f)
     local last_in, last_out = "", ""
     local state = "feeding"
@@ -254,8 +260,13 @@ function sink.error(err)
     end
 end
 
--- chains a sink with a filter
-function sink.chain(f, snk)
+-- chains a sink with one or several filter(s)
+function sink.chain(f, snk, ...)
+    if ... then
+        local args = { f, snk, ... }
+        snk = table.remove(args, #args)
+        f = filter.chain(unpack(args))
+    end
     base.assert(f and snk)
     return function(chunk, err)
         if chunk ~= "" then
diff --git a/src/luasocket.c b/src/luasocket.c
index e6ee747..7d9c802 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -17,7 +17,7 @@
 \*=========================================================================*/
 #include "lua.h"
 #include "lauxlib.h"
-
+#include "compat.h"
 
 /*=========================================================================*\
 * LuaSocket includes
@@ -64,7 +64,7 @@ static luaL_Reg func[] = {
 * Skip a few arguments
 \*-------------------------------------------------------------------------*/
 static int global_skip(lua_State *L) {
-    int amount = luaL_checkint(L, 1);
+    int amount = luaL_checkinteger(L, 1);
     int ret = lua_gettop(L) - amount - 1;
     return ret >= 0 ? ret : 0;
 }
@@ -78,26 +78,14 @@ static int global_unload(lua_State *L) {
     return 0;
 }
 
-#if LUA_VERSION_NUM > 501
-int luaL_typerror (lua_State *L, int narg, const char *tname) {
-  const char *msg = lua_pushfstring(L, "%s expected, got %s",
-                                    tname, luaL_typename(L, narg));
-  return luaL_argerror(L, narg, msg);
-}
-#endif
-
 /*-------------------------------------------------------------------------*\
 * Setup basic stuff.
 \*-------------------------------------------------------------------------*/
 static int base_open(lua_State *L) {
     if (socket_open()) {
         /* export functions (and leave namespace table on top of stack) */
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
         lua_newtable(L);
         luaL_setfuncs(L, func, 0);
-#else
-        luaL_openlib(L, "socket", func, 0);
-#endif
 #ifdef LUASOCKET_DEBUG
         lua_pushstring(L, "_DEBUG");
         lua_pushboolean(L, 1);
diff --git a/src/makefile b/src/makefile
index c24e61b..adf687f 100644
--- a/src/makefile
+++ b/src/makefile
@@ -20,15 +20,17 @@ PLAT?=linux
 # lua version to build against
 LUAV?=5.1
 
+# MYCFLAGS: to be set by user if needed
+MYCFLAGS=
+
+# MYLDFLAGS: to be set by user if needed
+MYLDFLAGS=
+
 # DEBUG: NODEBUG DEBUG
 # debug mode causes luasocket to collect and returns timing information useful
 # for testing and debugging luasocket itself
 DEBUG?=NODEBUG
 
-# COMPAT: COMPAT NOCOMPAT
-# when compiling for 5.2, use LUA_COMPAT_MODULE
-COMPAT?=NOCOMPAT
-
 # where lua headers are found for macosx builds
 # LUAINC_macosx:
 # /opt/local/include
@@ -40,7 +42,6 @@ LUAPREFIX_macosx?=/opt/local
 CDIR_macosx?=lib/lua/$(LUAV)
 LDIR_macosx?=share/lua/$(LUAV)
 
-
 # LUAINC_linux:
 # /usr/include/lua$(LUAV)
 # /usr/local/include
@@ -52,8 +53,17 @@ LUAPREFIX_linux?=/usr/local
 CDIR_linux?=lib/lua/$(LUAV)
 LDIR_linux?=share/lua/$(LUAV)
 
+# LUAINC_freebsd:
+# /usr/local/include/lua$(LUAV)
+# where lua headers are found for freebsd builds
+LUAINC_freebsd_base?=/usr/local/include/
+LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua$(LUAV)
+LUAPREFIX_freebsd?=/usr/local/
+CDIR_freebsd?=lib/lua/$(LUAV)
+LDIR_freebsd?=share/lua/$(LUAV)
+
 # where lua headers are found for mingw builds
-# LUAINC_mingw: 
+# LUAINC_mingw:
 # /opt/local/include
 LUAINC_mingw_base?=/usr/include
 LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV)
@@ -67,13 +77,21 @@ LDIR_mingw?=lua/$(LUAV)/lua
 # LUAINC_win32:
 # LUALIB_win32:
 # where lua headers and libraries are found for win32 builds
-LUAINC_win32_base?=
-LUAINC_win32?=$(LUAINC_win32_base)/lua/$(LUAV)
-PLATFORM_win32?=Release
 LUAPREFIX_win32?=
-CDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32)
-LDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32)/lua
-LUALIB_win32?=$(LUAPREFIX_win32)/lua/$(LUAV)/$(PLATFORM_win32)
+LUAINC_win32?=$(LUAPREFIX_win32)/include/lua/$(LUAV)
+PLATFORM_win32?=Release
+CDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)
+LDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)/lua
+LUALIB_win32?=$(LUAPREFIX_win32)/lib/lua/$(LUAV)/$(PLATFORM_win32)
+LUALIBNAME_win32?=lua$(subst .,,$(LUAV)).lib 
+
+
+# LUAINC_solaris:
+LUAINC_solaris_base?=/usr/include
+LUAINC_solaris?=$(LUAINC_solaris_base)/lua/$(LUAV)
+LUAPREFIX_solaris?=/usr/local
+CDIR_solaris?=lib/lua/$(LUAV)
+LDIR_solaris?=share/lua/$(LUAV)
 
 # prefix: /usr/local /usr /opt/local /sw
 # the top of the default install tree
@@ -121,7 +139,7 @@ print:
 #------
 # Supported platforms
 #
-PLATS= macosx linux win32 mingw
+PLATS= macosx linux win32 mingw solaris
 
 #------
 # Compiler and linker settings
@@ -129,11 +147,11 @@ PLATS= macosx linux win32 mingw
 SO_macosx=so
 O_macosx=o
 CC_macosx=gcc
-DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN -DLUA_$(COMPAT)_MODULE \
+DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN \
 	-DLUASOCKET_API='__attribute__((visibility("default")))' \
 	-DUNIX_API='__attribute__((visibility("default")))' \
 	-DMIME_API='__attribute__((visibility("default")))'
-CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \
+CFLAGS_macosx= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \
 	-fvisibility=hidden
 LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o 
 LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc
@@ -145,11 +163,11 @@ SOCKET_macosx=usocket.o
 SO_linux=so
 O_linux=o
 CC_linux=gcc
-DEF_linux=-DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \
+DEF_linux=-DLUASOCKET_$(DEBUG) \
 	-DLUASOCKET_API='__attribute__((visibility("default")))' \
 	-DUNIX_API='__attribute__((visibility("default")))' \
 	-DMIME_API='__attribute__((visibility("default")))'
-CFLAGS_linux= -I$(LUAINC) $(DEF) -pedantic -Wall -Wshadow -Wextra \
+CFLAGS_linux= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \
 	-Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden
 LDFLAGS_linux=-O -shared -fpic -o 
 LD_linux=gcc
@@ -157,14 +175,46 @@ SOCKET_linux=usocket.o
 
 #------
 # Compiler and linker settings
+# for FreeBSD
+SO_freebsd=so
+O_freebsd=o
+CC_freebsd=gcc
+DEF_freebsd=-DLUASOCKET_$(DEBUG) \
+	-DLUASOCKET_API='__attribute__((visibility("default")))' \
+	-DUNIX_API='__attribute__((visibility("default")))' \
+	-DMIME_API='__attribute__((visibility("default")))'
+CFLAGS_freebsd= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \
+	-Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden
+LDFLAGS_freebsd=-O -shared -fpic -o 
+LD_freebsd=gcc
+SOCKET_freebsd=usocket.o
+
+#------
+# Compiler and linker settings
+# for Solaris
+SO_solaris=so
+O_solaris=o
+CC_solaris=gcc
+DEF_solaris=-DLUASOCKET_$(DEBUG) \
+	-DLUASOCKET_API='__attribute__((visibility("default")))' \
+	-DUNIX_API='__attribute__((visibility("default")))' \
+	-DMIME_API='__attribute__((visibility("default")))'
+CFLAGS_solaris=-I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \
+	-Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden   
+LDFLAGS_solaris=-lnsl -lsocket -lresolv -O -shared -fpic -o 
+LD_solaris=gcc
+SOCKET_solaris=usocket.o
+
+#------
+# Compiler and linker settings
 # for MingW
 SO_mingw=dll
 O_mingw=o
 CC_mingw=gcc
-DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \
+DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) \
 	-DWINVER=0x0501 -DLUASOCKET_API='__declspec(dllexport)' \
 	-DMIME_API='__declspec(dllexport)'
-CFLAGS_mingw= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \
+CFLAGS_mingw= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \
 	-fvisibility=hidden
 LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o 
 LD_mingw=gcc
@@ -179,8 +229,7 @@ O_win32=obj
 CC_win32=cl
 DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \
      //D "LUASOCKET_API=__declspec(dllexport)" //D "_CRT_SECURE_NO_WARNINGS" \
-     //D "_WINDLL" //D "LUA_$(COMPAT)_MODULE" \
-	 //D "MIME_API=__declspec(dllexport)" \
+     //D "_WINDLL" //D "MIME_API=__declspec(dllexport)" \
      //D "LUASOCKET_$(DEBUG)" 
 CFLAGS_win32=//I "$(LUAINC)" $(DEF) //O2 //Ot //MD //W3 //nologo
 LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \
@@ -188,7 +237,7 @@ LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \
     //MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
 	//SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \
     //MACHINE:X86 /LIBPATH:"$(shell cmd //c echo $(LUALIB))" \
-	lua$(subst .,,$(LUAV)).lib ws2_32.lib //OUT:
+	$(LUALIBNAME_win32) ws2_32.lib //OUT:
 LD_win32=cl
 SOCKET_win32=wsocket.obj
 
@@ -204,8 +253,8 @@ SO=$(SO_$(PLAT))
 O=$(O_$(PLAT))
 SOCKET_V=3.0-rc1
 MIME_V=1.0.3
-SOCKET_SO=socket.$(SO).$(SOCKET_V)
-MIME_SO=mime.$(SO).$(MIME_V)
+SOCKET_SO=socket-$(SOCKET_V).$(SO)
+MIME_SO=mime-$(MIME_V).$(SO)
 UNIX_SO=unix.$(SO)
 SERIAL_SO=serial.$(SO)
 SOCKET=$(SOCKET_$(PLAT))
@@ -215,8 +264,8 @@ SOCKET=$(SOCKET_$(PLAT))
 #
 CC=$(CC_$(PLAT))
 DEF=$(DEF_$(PLAT))
-CFLAGS=$(CFLAGS_$(PLAT))
-LDFLAGS=$(LDFLAGS_$(PLAT))
+CFLAGS=$(MYCFLAGS) $(CFLAGS_$(PLAT))
+LDFLAGS=$(MYLDFLAGS) $(LDFLAGS_$(PLAT))
 LD=$(LD_$(PLAT))
 LUAINC= $(LUAINC_$(PLAT))
 LUALIB= $(LUALIB_$(PLAT))
@@ -230,6 +279,7 @@ SOCKET_OBJS= \
 	buffer.$(O) \
 	io.$(O) \
 	auxiliar.$(O) \
+	compat.$(O) \
 	options.$(O) \
 	inet.$(O) \
 	$(SOCKET) \
@@ -242,7 +292,8 @@ SOCKET_OBJS= \
 # Modules belonging mime-core
 #
 MIME_OBJS= \
-	mime.$(O)
+	mime.$(O) \
+	compat.$(O)
 
 #------
 # Modules belonging unix (local domain sockets)
@@ -259,7 +310,7 @@ UNIX_OBJS=\
 #------
 # Modules belonging to serial (device streams)
 #
-SERIAL_OBJS:=\
+SERIAL_OBJS=\
 	buffer.$(O) \
 	auxiliar.$(O) \
 	options.$(O) \
@@ -289,6 +340,10 @@ TO_TOP_LDIR= \
 #
 default: $(PLAT)
 
+
+freebsd:
+	$(MAKE) all-unix PLAT=freebsd
+
 macosx:
 	$(MAKE) all-unix PLAT=macosx
 
@@ -300,6 +355,9 @@ linux:
 
 mingw:
 	$(MAKE) all PLAT=mingw
+	
+solaris:
+	$(MAKE) all-unix PLAT=solaris
 
 none:
 	@echo "Please run"
@@ -349,6 +407,7 @@ clean:
 #------
 # List of dependencies
 #
+compat.$(O): compat.c compat.h
 auxiliar.$(O): auxiliar.c auxiliar.h
 buffer.$(O): buffer.c buffer.h io.h timeout.h
 except.$(O): except.c except.h
diff --git a/src/mbox.lua b/src/mbox.lua
index 7724ae2..ed9e781 100644
--- a/src/mbox.lua
+++ b/src/mbox.lua
@@ -61,7 +61,7 @@ function _M.parse_from(from)
 end
 
 function _M.split_mbox(mbox_s)
-    mbox = {}
+    local mbox = {}
     mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n"
     local nj, i, j = 1, 1, 1
     while 1 do
diff --git a/src/mime.c b/src/mime.c
index dd37dcf..ed44104 100644
--- a/src/mime.c
+++ b/src/mime.c
@@ -6,10 +6,7 @@
 
 #include "lua.h"
 #include "lauxlib.h"
-
-#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
-#include "compat-5.1.h"
-#endif
+#include "compat.h"
 
 #include "mime.h"
 
@@ -41,7 +38,7 @@ static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
 static void qpsetup(UC *class, UC *unbase);
 static void qpquote(UC c, luaL_Buffer *buffer);
 static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
-static size_t qpencode(UC c, UC *input, size_t size, 
+static size_t qpencode(UC c, UC *input, size_t size,
         const char *marker, luaL_Buffer *buffer);
 static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer);
 
@@ -81,12 +78,8 @@ static UC b64unbase[256];
 \*-------------------------------------------------------------------------*/
 MIME_API int luaopen_mime_core(lua_State *L)
 {
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
     lua_newtable(L);
     luaL_setfuncs(L, func, 0);
-#else
-    luaL_openlib(L, "mime", func, 0);
-#endif
     /* make version string available to scripts */
     lua_pushstring(L, "_VERSION");
     lua_pushstring(L, MIME_VERSION);
@@ -103,15 +96,15 @@ MIME_API int luaopen_mime_core(lua_State *L)
 /*-------------------------------------------------------------------------*\
 * Incrementaly breaks a string into lines. The string can have CRLF breaks.
 * A, n = wrp(l, B, length)
-* A is a copy of B, broken into lines of at most 'length' bytes. 
-* 'l' is how many bytes are left for the first line of B. 
-* 'n' is the number of bytes left in the last line of A. 
+* A is a copy of B, broken into lines of at most 'length' bytes.
+* 'l' is how many bytes are left for the first line of B.
+* 'n' is the number of bytes left in the last line of A.
 \*-------------------------------------------------------------------------*/
 static int mime_global_wrp(lua_State *L)
 {
     size_t size = 0;
     int left = (int) luaL_checknumber(L, 1);
-    const UC *input = (UC *) luaL_optlstring(L, 2, NULL, &size);
+    const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size);
     const UC *last = input + size;
     int length = (int) luaL_optnumber(L, 3, 76);
     luaL_Buffer buffer;
@@ -123,7 +116,7 @@ static int mime_global_wrp(lua_State *L)
         else lua_pushnil(L);
         lua_pushnumber(L, length);
         return 2;
-    } 
+    }
     luaL_buffinit(L, &buffer);
     while (input < last) {
         switch (*input) {
@@ -150,9 +143,9 @@ static int mime_global_wrp(lua_State *L)
 }
 
 /*-------------------------------------------------------------------------*\
-* Fill base64 decode map. 
+* Fill base64 decode map.
 \*-------------------------------------------------------------------------*/
-static void b64setup(UC *unbase) 
+static void b64setup(UC *unbase)
 {
     int i;
     for (i = 0; i <= 255; i++) unbase[i] = (UC) 255;
@@ -161,11 +154,11 @@ static void b64setup(UC *unbase)
 }
 
 /*-------------------------------------------------------------------------*\
-* Acumulates bytes in input buffer until 3 bytes are available. 
+* Acumulates bytes in input buffer until 3 bytes are available.
 * Translate the 3 bytes into Base64 form and append to buffer.
 * Returns new number of bytes in buffer.
 \*-------------------------------------------------------------------------*/
-static size_t b64encode(UC c, UC *input, size_t size, 
+static size_t b64encode(UC c, UC *input, size_t size,
         luaL_Buffer *buffer)
 {
     input[size++] = c;
@@ -174,7 +167,7 @@ static size_t b64encode(UC c, UC *input, size_t size,
         unsigned long value = 0;
         value += input[0]; value <<= 8;
         value += input[1]; value <<= 8;
-        value += input[2]; 
+        value += input[2];
         code[3] = b64base[value & 0x3f]; value >>= 6;
         code[2] = b64base[value & 0x3f]; value >>= 6;
         code[1] = b64base[value & 0x3f]; value >>= 6;
@@ -186,11 +179,11 @@ static size_t b64encode(UC c, UC *input, size_t size,
 }
 
 /*-------------------------------------------------------------------------*\
-* Encodes the Base64 last 1 or 2 bytes and adds padding '=' 
+* Encodes the Base64 last 1 or 2 bytes and adds padding '='
 * Result, if any, is appended to buffer.
 * Returns 0.
 \*-------------------------------------------------------------------------*/
-static size_t b64pad(const UC *input, size_t size, 
+static size_t b64pad(const UC *input, size_t size,
         luaL_Buffer *buffer)
 {
     unsigned long value = 0;
@@ -203,7 +196,7 @@ static size_t b64pad(const UC *input, size_t size,
             luaL_addlstring(buffer, (char *) code, 4);
             break;
         case 2:
-            value = input[0]; value <<= 8; 
+            value = input[0]; value <<= 8;
             value |= input[1]; value <<= 2;
             code[2] = b64base[value & 0x3f]; value >>= 6;
             code[1] = b64base[value & 0x3f]; value >>= 6;
@@ -217,11 +210,11 @@ static size_t b64pad(const UC *input, size_t size,
 }
 
 /*-------------------------------------------------------------------------*\
-* Acumulates bytes in input buffer until 4 bytes are available. 
+* Acumulates bytes in input buffer until 4 bytes are available.
 * Translate the 4 bytes from Base64 form and append to buffer.
 * Returns new number of bytes in buffer.
 \*-------------------------------------------------------------------------*/
-static size_t b64decode(UC c, UC *input, size_t size, 
+static size_t b64decode(UC c, UC *input, size_t size,
         luaL_Buffer *buffer)
 {
     /* ignore invalid characters */
@@ -239,7 +232,7 @@ static size_t b64decode(UC c, UC *input, size_t size,
         decoded[1] = (UC) (value & 0xff); value >>= 8;
         decoded[0] = (UC) value;
         /* take care of paddding */
-        valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3; 
+        valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3;
         luaL_addlstring(buffer, (char *) decoded, valid);
         return 0;
     /* need more data */
@@ -251,7 +244,7 @@ static size_t b64decode(UC c, UC *input, size_t size,
 * A, B = b64(C, D)
 * A is the encoded version of the largest prefix of C .. D that is
 * divisible by 3. B has the remaining bytes of C .. D, *without* encoding.
-* The easiest thing would be to concatenate the two strings and 
+* The easiest thing would be to concatenate the two strings and
 * encode the result, but we can't afford that or Lua would dupplicate
 * every chunk we received.
 \*-------------------------------------------------------------------------*/
@@ -259,7 +252,7 @@ static int mime_global_b64(lua_State *L)
 {
     UC atom[3];
     size_t isize = 0, asize = 0;
-    const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize);
+    const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
     const UC *last = input + isize;
     luaL_Buffer buffer;
     /* end-of-input blackhole */
@@ -272,9 +265,9 @@ static int mime_global_b64(lua_State *L)
     lua_settop(L, 2);
     /* process first part of the input */
     luaL_buffinit(L, &buffer);
-    while (input < last) 
+    while (input < last)
         asize = b64encode(*input++, atom, asize, &buffer);
-    input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
+    input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
     /* if second part is nil, we are done */
     if (!input) {
         size_t osize = 0;
@@ -288,7 +281,7 @@ static int mime_global_b64(lua_State *L)
     }
     /* otherwise process the second part */
     last = input + isize;
-    while (input < last) 
+    while (input < last)
         asize = b64encode(*input++, atom, asize, &buffer);
     luaL_pushresult(&buffer);
     lua_pushlstring(L, (char *) atom, asize);
@@ -305,7 +298,7 @@ static int mime_global_unb64(lua_State *L)
 {
     UC atom[4];
     size_t isize = 0, asize = 0;
-    const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize);
+    const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
     const UC *last = input + isize;
     luaL_Buffer buffer;
     /* end-of-input blackhole */
@@ -318,9 +311,9 @@ static int mime_global_unb64(lua_State *L)
     lua_settop(L, 2);
     /* process first part of the input */
     luaL_buffinit(L, &buffer);
-    while (input < last) 
+    while (input < last)
         asize = b64decode(*input++, atom, asize, &buffer);
-    input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
+    input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
     /* if second is nil, we are done */
     if (!input) {
         size_t osize = 0;
@@ -333,7 +326,7 @@ static int mime_global_unb64(lua_State *L)
     }
     /* otherwise, process the rest of the input */
     last = input + isize;
-    while (input < last) 
+    while (input < last)
         asize = b64decode(*input++, atom, asize, &buffer);
     luaL_pushresult(&buffer);
     lua_pushlstring(L, (char *) atom, asize);
@@ -349,7 +342,7 @@ static int mime_global_unb64(lua_State *L)
 * 9 and 32 can be plain, unless in the end of a line, where must be =XX
 * encoded lines must be no longer than 76 not counting CRLF
 * soft line-break are =CRLF
-* To encode one byte, we need to see the next two. 
+* To encode one byte, we need to see the next two.
 * Worst case is when we see a space, and wonder if a CRLF is comming
 \*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*\
@@ -362,7 +355,7 @@ static void qpsetup(UC *cl, UC *unbase)
     for (i = 0; i < 256; i++) cl[i] = QP_QUOTED;
     for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN;
     for (i = 62; i <= 126; i++) cl[i] = QP_PLAIN;
-    cl['\t'] = QP_IF_LAST; 
+    cl['\t'] = QP_IF_LAST;
     cl[' '] = QP_IF_LAST;
     cl['\r'] = QP_CR;
     for (i = 0; i < 256; i++) unbase[i] = 255;
@@ -388,9 +381,9 @@ static void qpquote(UC c, luaL_Buffer *buffer)
 
 /*-------------------------------------------------------------------------*\
 * Accumulate characters until we are sure about how to deal with them.
-* Once we are sure, output to the buffer, in the correct form. 
+* Once we are sure, output to the buffer, in the correct form.
 \*-------------------------------------------------------------------------*/
-static size_t qpencode(UC c, UC *input, size_t size, 
+static size_t qpencode(UC c, UC *input, size_t size,
         const char *marker, luaL_Buffer *buffer)
 {
     input[size++] = c;
@@ -431,7 +424,7 @@ static size_t qpencode(UC c, UC *input, size_t size,
 }
 
 /*-------------------------------------------------------------------------*\
-* Deal with the final characters 
+* Deal with the final characters
 \*-------------------------------------------------------------------------*/
 static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
 {
@@ -448,8 +441,8 @@ static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
 * Incrementally converts a string to quoted-printable
 * A, B = qp(C, D, marker)
 * Marker is the text to be used to replace CRLF sequences found in A.
-* A is the encoded version of the largest prefix of C .. D that 
-* can be encoded without doubts. 
+* A is the encoded version of the largest prefix of C .. D that
+* can be encoded without doubts.
 * B has the remaining bytes of C .. D, *without* encoding.
 \*-------------------------------------------------------------------------*/
 static int mime_global_qp(lua_State *L)
@@ -457,7 +450,7 @@ static int mime_global_qp(lua_State *L)
 
     size_t asize = 0, isize = 0;
     UC atom[3];
-    const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize);
+    const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
     const UC *last = input + isize;
     const char *marker = luaL_optstring(L, 3, CRLF);
     luaL_Buffer buffer;
@@ -473,7 +466,7 @@ static int mime_global_qp(lua_State *L)
     luaL_buffinit(L, &buffer);
     while (input < last)
         asize = qpencode(*input++, atom, asize, marker, &buffer);
-    input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
+    input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
     /* if second part is nil, we are done */
     if (!input) {
         asize = qppad(atom, asize, &buffer);
@@ -493,7 +486,7 @@ static int mime_global_qp(lua_State *L)
 
 /*-------------------------------------------------------------------------*\
 * Accumulate characters until we are sure about how to deal with them.
-* Once we are sure, output the to the buffer, in the correct form. 
+* Once we are sure, output the to the buffer, in the correct form.
 \*-------------------------------------------------------------------------*/
 static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
     int d;
@@ -501,8 +494,8 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
     /* deal with all characters we can deal */
     switch (input[0]) {
         /* if we have an escape character */
-        case '=': 
-            if (size < 3) return size; 
+        case '=':
+            if (size < 3) return size;
             /* eliminate soft line break */
             if (input[1] == '\r' && input[2] == '\n') return 0;
             /* decode quoted representation */
@@ -512,7 +505,7 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
             else luaL_addchar(buffer, (char) ((c << 4) + d));
             return 0;
         case '\r':
-            if (size < 2) return size; 
+            if (size < 2) return size;
             if (input[1] == '\n') luaL_addlstring(buffer, (char *)input, 2);
             return 0;
         default:
@@ -525,15 +518,15 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
 /*-------------------------------------------------------------------------*\
 * Incrementally decodes a string in quoted-printable
 * A, B = qp(C, D)
-* A is the decoded version of the largest prefix of C .. D that 
-* can be decoded without doubts. 
+* A is the decoded version of the largest prefix of C .. D that
+* can be decoded without doubts.
 * B has the remaining bytes of C .. D, *without* decoding.
 \*-------------------------------------------------------------------------*/
 static int mime_global_unqp(lua_State *L)
 {
     size_t asize = 0, isize = 0;
     UC atom[3];
-    const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize);
+    const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
     const UC *last = input + isize;
     luaL_Buffer buffer;
     /* end-of-input blackhole */
@@ -548,14 +541,14 @@ static int mime_global_unqp(lua_State *L)
     luaL_buffinit(L, &buffer);
     while (input < last)
         asize = qpdecode(*input++, atom, asize, &buffer);
-    input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
+    input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
     /* if second part is nil, we are done */
     if (!input) {
         luaL_pushresult(&buffer);
         if (!(*lua_tostring(L, -1))) lua_pushnil(L);
         lua_pushnil(L);
         return 2;
-    } 
+    }
     /* otherwise process rest of input */
     last = input + isize;
     while (input < last)
@@ -568,9 +561,9 @@ static int mime_global_unqp(lua_State *L)
 /*-------------------------------------------------------------------------*\
 * Incrementally breaks a quoted-printed string into lines
 * A, n = qpwrp(l, B, length)
-* A is a copy of B, broken into lines of at most 'length' bytes. 
-* 'l' is how many bytes are left for the first line of B. 
-* 'n' is the number of bytes left in the last line of A. 
+* A is a copy of B, broken into lines of at most 'length' bytes.
+* 'l' is how many bytes are left for the first line of B.
+* 'n' is the number of bytes left in the last line of A.
 * There are two complications: lines can't be broken in the middle
 * of an encoded =XX, and there might be line breaks already
 \*-------------------------------------------------------------------------*/
@@ -578,7 +571,7 @@ static int mime_global_qpwrp(lua_State *L)
 {
     size_t size = 0;
     int left = (int) luaL_checknumber(L, 1);
-    const UC *input = (UC *) luaL_optlstring(L, 2, NULL, &size);
+    const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size);
     const UC *last = input + size;
     int length = (int) luaL_optnumber(L, 3, 76);
     luaL_Buffer buffer;
@@ -603,11 +596,11 @@ static int mime_global_qpwrp(lua_State *L)
                 if (left <= 3) {
                     left = length;
                     luaL_addstring(&buffer, EQCRLF);
-                } 
+                }
                 luaL_addchar(&buffer, *input);
                 left--;
                 break;
-            default: 
+            default:
                 if (left <= 1) {
                     left = length;
                     luaL_addstring(&buffer, EQCRLF);
@@ -635,7 +628,7 @@ static int mime_global_qpwrp(lua_State *L)
 * last is the previous character
 \*-------------------------------------------------------------------------*/
 #define eolcandidate(c) (c == '\r' || c == '\n')
-static int eolprocess(int c, int last, const char *marker, 
+static int eolprocess(int c, int last, const char *marker,
         luaL_Buffer *buffer)
 {
     if (eolcandidate(c)) {
@@ -653,15 +646,15 @@ static int eolprocess(int c, int last, const char *marker,
 }
 
 /*-------------------------------------------------------------------------*\
-* Converts a string to uniform EOL convention. 
+* Converts a string to uniform EOL convention.
 * A, n = eol(o, B, marker)
 * A is the converted version of the largest prefix of B that can be
-* converted unambiguously. 'o' is the context returned by the previous 
+* converted unambiguously. 'o' is the context returned by the previous
 * call. 'n' is the new context.
 \*-------------------------------------------------------------------------*/
 static int mime_global_eol(lua_State *L)
 {
-    int ctx = luaL_checkint(L, 1);
+    int ctx = luaL_checkinteger(L, 1);
     size_t isize = 0;
     const char *input = luaL_optlstring(L, 2, NULL, &isize);
     const char *last = input + isize;
@@ -683,18 +676,18 @@ static int mime_global_eol(lua_State *L)
 }
 
 /*-------------------------------------------------------------------------*\
-* Takes one byte and stuff it if needed. 
+* Takes one byte and stuff it if needed.
 \*-------------------------------------------------------------------------*/
 static size_t dot(int c, size_t state, luaL_Buffer *buffer)
 {
     luaL_addchar(buffer, (char) c);
     switch (c) {
-        case '\r': 
+        case '\r':
             return 1;
-        case '\n': 
-            return (state == 1)? 2: 0; 
-        case '.':  
-            if (state == 2) 
+        case '\n':
+            return (state == 1)? 2: 0;
+        case '.':
+            if (state == 2)
                 luaL_addchar(buffer, '.');
         default:
             return 0;
@@ -719,7 +712,7 @@ static int mime_global_dot(lua_State *L)
     }
     /* process all input */
     luaL_buffinit(L, &buffer);
-    while (input < last) 
+    while (input < last)
         state = dot(*input++, state, &buffer);
     luaL_pushresult(&buffer);
     lua_pushnumber(L, (lua_Number) state);
diff --git a/src/options.c b/src/options.c
index 8ac2a14..20f4c28 100644
--- a/src/options.c
+++ b/src/options.c
@@ -1,8 +1,8 @@
 /*=========================================================================*\
-* Common option interface 
+* Common option interface
 * LuaSocket toolkit
 \*=========================================================================*/
-#include <string.h> 
+#include <string.h>
 
 #include "lauxlib.h"
 
@@ -20,9 +20,9 @@ static int opt_setboolean(lua_State *L, p_socket ps, int level, int name);
 static int opt_getboolean(lua_State *L, p_socket ps, int level, int name);
 static int opt_setint(lua_State *L, p_socket ps, int level, int name);
 static int opt_getint(lua_State *L, p_socket ps, int level, int name);
-static int opt_set(lua_State *L, p_socket ps, int level, int name, 
+static int opt_set(lua_State *L, p_socket ps, int level, int name,
         void *val, int len);
-static int opt_get(lua_State *L, p_socket ps, int level, int name, 
+static int opt_get(lua_State *L, p_socket ps, int level, int name,
         void *val, int* len);
 
 /*=========================================================================*\
@@ -60,29 +60,29 @@ int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps)
 /* enables reuse of local address */
 int opt_set_reuseaddr(lua_State *L, p_socket ps)
 {
-    return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); 
+    return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
 }
 
 int opt_get_reuseaddr(lua_State *L, p_socket ps)
 {
-    return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); 
+    return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
 }
 
 /* enables reuse of local port */
 int opt_set_reuseport(lua_State *L, p_socket ps)
 {
-    return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); 
+    return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
 }
 
 int opt_get_reuseport(lua_State *L, p_socket ps)
 {
-    return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); 
+    return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
 }
 
 /* disables the Naggle algorithm */
 int opt_set_tcp_nodelay(lua_State *L, p_socket ps)
 {
-    return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); 
+    return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
 }
 
 int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
@@ -92,12 +92,12 @@ int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
 
 int opt_set_keepalive(lua_State *L, p_socket ps)
 {
-    return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); 
+    return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
 }
 
 int opt_get_keepalive(lua_State *L, p_socket ps)
 {
-    return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); 
+    return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
 }
 
 int opt_set_dontroute(lua_State *L, p_socket ps)
@@ -105,11 +105,21 @@ int opt_set_dontroute(lua_State *L, p_socket ps)
     return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
 }
 
+int opt_get_dontroute(lua_State *L, p_socket ps)
+{
+    return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
+}
+
 int opt_set_broadcast(lua_State *L, p_socket ps)
 {
     return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST);
 }
 
+int opt_get_broadcast(lua_State *L, p_socket ps)
+{
+    return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST);
+}
+
 int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps)
 {
   return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS);
@@ -156,12 +166,12 @@ int opt_set_linger(lua_State *L, p_socket ps)
     if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
     lua_pushstring(L, "on");
     lua_gettable(L, 3);
-    if (!lua_isboolean(L, -1)) 
+    if (!lua_isboolean(L, -1))
         luaL_argerror(L, 3, "boolean 'on' field expected");
     li.l_onoff = (u_short) lua_toboolean(L, -1);
     lua_pushstring(L, "timeout");
     lua_gettable(L, 3);
-    if (!lua_isnumber(L, -1)) 
+    if (!lua_isnumber(L, -1))
         luaL_argerror(L, 3, "number 'timeout' field expected");
     li.l_linger = (u_short) lua_tonumber(L, -1);
     return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li));
@@ -194,7 +204,7 @@ int opt_set_ip_multicast_if(lua_State *L, p_socket ps)
     val.s_addr = htonl(INADDR_ANY);
     if (strcmp(address, "*") && !inet_aton(address, &val))
         luaL_argerror(L, 3, "ip expected");
-    return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF, 
+    return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF,
         (char *) &val, sizeof(val));
 }
 
@@ -250,17 +260,17 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name)
     if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
     lua_pushstring(L, "multiaddr");
     lua_gettable(L, 3);
-    if (!lua_isstring(L, -1)) 
+    if (!lua_isstring(L, -1))
         luaL_argerror(L, 3, "string 'multiaddr' field expected");
-    if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) 
+    if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr))
         luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
     lua_pushstring(L, "interface");
     lua_gettable(L, 3);
-    if (!lua_isstring(L, -1)) 
+    if (!lua_isstring(L, -1))
         luaL_argerror(L, 3, "string 'interface' field expected");
     val.imr_interface.s_addr = htonl(INADDR_ANY);
     if (strcmp(lua_tostring(L, -1), "*") &&
-            !inet_aton(lua_tostring(L, -1), &val.imr_interface)) 
+            !inet_aton(lua_tostring(L, -1), &val.imr_interface))
         luaL_argerror(L, 3, "invalid 'interface' ip address");
     return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
 }
@@ -272,14 +282,14 @@ static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name)
     if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
     lua_pushstring(L, "multiaddr");
     lua_gettable(L, 3);
-    if (!lua_isstring(L, -1)) 
+    if (!lua_isstring(L, -1))
         luaL_argerror(L, 3, "string 'multiaddr' field expected");
-    if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) 
+    if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr))
         luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
     lua_pushstring(L, "interface");
     lua_gettable(L, 3);
     /* By default we listen to interface on default route
-     * (sigh). However, interface= can override it. We should 
+     * (sigh). However, interface= can override it. We should
      * support either number, or name for it. Waiting for
      * windows port of if_nametoindex */
     if (!lua_isnil(L, -1)) {
@@ -291,7 +301,7 @@ static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name)
     return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
 }
 
-static 
+static
 int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
 {
     socklen_t socklen = *len;
@@ -304,7 +314,7 @@ int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
     return 0;
 }
 
-static 
+static
 int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
 {
     if (setsockopt(*ps, level, name, (char *) val, len) < 0) {
diff --git a/src/options.h b/src/options.h
index 5657a06..19ba0df 100644
--- a/src/options.h
+++ b/src/options.h
@@ -21,7 +21,6 @@ typedef t_opt *p_opt;
 /* supported options for setoption */
 int opt_set_dontroute(lua_State *L, p_socket ps);
 int opt_set_broadcast(lua_State *L, p_socket ps);
-int opt_set_reuseaddr(lua_State *L, p_socket ps);
 int opt_set_tcp_nodelay(lua_State *L, p_socket ps);
 int opt_set_keepalive(lua_State *L, p_socket ps);
 int opt_set_linger(lua_State *L, p_socket ps);
@@ -40,18 +39,21 @@ int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps);
 int opt_set_ip6_v6only(lua_State *L, p_socket ps);
 
 /* supported options for getoption */
+int opt_get_dontroute(lua_State *L, p_socket ps);
+int opt_get_broadcast(lua_State *L, p_socket ps);
 int opt_get_reuseaddr(lua_State *L, p_socket ps);
+int opt_get_reuseport(lua_State *L, p_socket ps);
 int opt_get_tcp_nodelay(lua_State *L, p_socket ps);
 int opt_get_keepalive(lua_State *L, p_socket ps);
 int opt_get_linger(lua_State *L, p_socket ps);
-int opt_get_reuseaddr(lua_State *L, p_socket ps);
 int opt_get_ip_multicast_loop(lua_State *L, p_socket ps);
 int opt_get_ip_multicast_if(lua_State *L, p_socket ps);
 int opt_get_error(lua_State *L, p_socket ps);
 int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps);
 int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps);
 int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps);
-int opt_get_ip6_v6only(lua_State *L, p_socket ps); 
+int opt_get_ip6_v6only(lua_State *L, p_socket ps);
+int opt_get_reuseport(lua_State *L, p_socket ps);
 
 /* invokes the appropriate option handler */
 int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps);
diff --git a/src/pierror.h b/src/pierror.h
new file mode 100644
index 0000000..cb773ab
--- /dev/null
+++ b/src/pierror.h
@@ -0,0 +1,28 @@
+#ifndef PIERROR_H
+#define PIERROR_H
+/*=========================================================================*\
+* Error messages
+* Defines platform independent error messages
+\*=========================================================================*/
+
+#define PIE_HOST_NOT_FOUND "host not found"
+#define PIE_ADDRINUSE      "address already in use"
+#define PIE_ISCONN         "already connected"
+#define PIE_ACCESS         "permission denied"
+#define PIE_CONNREFUSED    "connection refused"
+#define PIE_CONNABORTED    "closed"
+#define PIE_CONNRESET      "closed"
+#define PIE_TIMEDOUT       "timeout"
+#define PIE_AGAIN          "temporary failure in name resolution"
+#define PIE_BADFLAGS       "invalid value for ai_flags"
+#define PIE_BADHINTS       "invalid value for hints"
+#define PIE_FAIL           "non-recoverable failure in name resolution"
+#define PIE_FAMILY         "ai_family not supported"
+#define PIE_MEMORY         "memory allocation failure"
+#define PIE_NONAME         "host or service not provided, or not known"
+#define PIE_OVERFLOW       "argument buffer overflow"
+#define PIE_PROTOCOL       "resolved protocol is unknown"
+#define PIE_SERVICE        "service not supported for socket type"
+#define PIE_SOCKTYPE       "ai_socktype not supported"
+
+#endif
diff --git a/src/select.c b/src/select.c
index fafaa62..9d133b7 100644
--- a/src/select.c
+++ b/src/select.c
@@ -6,6 +6,7 @@
 
 #include "lua.h"
 #include "lauxlib.h"
+#include "compat.h"
 
 #include "socket.h"
 #include "timeout.h"
@@ -16,10 +17,10 @@
 \*=========================================================================*/
 static t_socket getfd(lua_State *L);
 static int dirty(lua_State *L);
-static void collect_fd(lua_State *L, int tab, int itab, 
+static void collect_fd(lua_State *L, int tab, int itab,
         fd_set *set, t_socket *max_fd);
 static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set);
-static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, 
+static void return_fd(lua_State *L, fd_set *set, t_socket max_fd,
         int itab, int tab, int start);
 static void make_assoc(lua_State *L, int tab);
 static int global_select(lua_State *L);
@@ -38,13 +39,12 @@ static luaL_Reg func[] = {
 \*-------------------------------------------------------------------------*/
 int select_open(lua_State *L) {
     lua_pushstring(L, "_SETSIZE");
-    lua_pushnumber(L, FD_SETSIZE);
+    lua_pushinteger(L, FD_SETSIZE);
+    lua_rawset(L, -3);
+    lua_pushstring(L, "_SOCKETINVALID");
+    lua_pushinteger(L, SOCKET_INVALID);
     lua_rawset(L, -3);
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
     luaL_setfuncs(L, func, 0);
-#else
-    luaL_openlib(L, NULL, func, 0);
-#endif
     return 0;
 }
 
@@ -98,10 +98,10 @@ static t_socket getfd(lua_State *L) {
         lua_pushvalue(L, -2);
         lua_call(L, 1, 1);
         if (lua_isnumber(L, -1)) {
-            double numfd = lua_tonumber(L, -1); 
+            double numfd = lua_tonumber(L, -1);
             fd = (numfd >= 0.0)? (t_socket) numfd: SOCKET_INVALID;
         }
-    } 
+    }
     lua_pop(L, 1);
     return fd;
 }
@@ -114,12 +114,12 @@ static int dirty(lua_State *L) {
         lua_pushvalue(L, -2);
         lua_call(L, 1, 1);
         is = lua_toboolean(L, -1);
-    } 
+    }
     lua_pop(L, 1);
     return is;
 }
 
-static void collect_fd(lua_State *L, int tab, int itab, 
+static void collect_fd(lua_State *L, int tab, int itab,
         fd_set *set, t_socket *max_fd) {
     int i = 1, n = 0;
     /* nil is the same as an empty table */
@@ -139,16 +139,16 @@ static void collect_fd(lua_State *L, int tab, int itab,
         if (fd != SOCKET_INVALID) {
             /* make sure we don't overflow the fd_set */
 #ifdef _WIN32
-            if (n >= FD_SETSIZE) 
+            if (n >= FD_SETSIZE)
                 luaL_argerror(L, tab, "too many sockets");
 #else
-            if (fd >= FD_SETSIZE) 
+            if (fd >= FD_SETSIZE)
                 luaL_argerror(L, tab, "descriptor too large for set size");
 #endif
             FD_SET(fd, set);
             n++;
             /* keep track of the largest descriptor so far */
-            if (*max_fd == SOCKET_INVALID || *max_fd < fd) 
+            if (*max_fd == SOCKET_INVALID || *max_fd < fd)
                 *max_fd = fd;
             /* make sure we can map back from descriptor to the object */
             lua_pushnumber(L, (lua_Number) fd);
@@ -162,9 +162,9 @@ static void collect_fd(lua_State *L, int tab, int itab,
 
 static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) {
     int ndirty = 0, i = 1;
-    if (lua_isnil(L, tab)) 
+    if (lua_isnil(L, tab))
         return 0;
-    for ( ;; ) { 
+    for ( ;; ) {
         t_socket fd;
         lua_pushnumber(L, i);
         lua_gettable(L, tab);
@@ -185,7 +185,7 @@ static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) {
     return ndirty;
 }
 
-static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, 
+static void return_fd(lua_State *L, fd_set *set, t_socket max_fd,
         int itab, int tab, int start) {
     t_socket fd;
     for (fd = 0; fd < max_fd; fd++) {
diff --git a/src/serial.c b/src/serial.c
index 583d4e5..7bdb21c 100644
--- a/src/serial.c
+++ b/src/serial.c
@@ -2,7 +2,7 @@
 * Serial stream
 * LuaSocket toolkit
 \*=========================================================================*/
-#include <string.h> 
+#include <string.h>
 
 #include "lua.h"
 #include "lauxlib.h"
@@ -11,7 +11,7 @@
 #include "socket.h"
 #include "options.h"
 #include "unix.h"
-#include <sys/un.h> 
+#include <sys/un.h>
 
 /*
 Reuses userdata definition from unix.h, since it is useful for all
@@ -54,15 +54,6 @@ static luaL_Reg serial_methods[] = {
     {NULL,          NULL}
 };
 
-/* our socket creation function */
-/* this is an ad-hoc module that returns a single function 
- * as such, do not include other functions in this array. */
-static luaL_Reg func[] = {
-    {"serial", global_create},
-    {NULL,          NULL}
-};
-
-
 /*-------------------------------------------------------------------------*\
 * Initializes module
 \*-------------------------------------------------------------------------*/
@@ -71,14 +62,7 @@ LUASOCKET_API int luaopen_socket_serial(lua_State *L) {
     auxiliar_newclass(L, "serial{client}", serial_methods);
     /* create class groups */
     auxiliar_add2group(L, "serial{client}", "serial{any}");
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
-    lua_pushcfunction(L, global_create);
-    (void) func;
-#else
-    /* set function into socket namespace */
-    luaL_openlib(L, "socket", func, 0);
     lua_pushcfunction(L, global_create);
-#endif
     return 1;
 }
 
@@ -120,7 +104,7 @@ static int meth_getfd(lua_State *L) {
 /* this is very dangerous, but can be handy for those that are brave enough */
 static int meth_setfd(lua_State *L) {
     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
-    un->sock = (t_socket) luaL_checknumber(L, 2); 
+    un->sock = (t_socket) luaL_checknumber(L, 2);
     return 0;
 }
 
@@ -131,7 +115,7 @@ static int meth_dirty(lua_State *L) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Closes socket used by object 
+* Closes socket used by object
 \*-------------------------------------------------------------------------*/
 static int meth_close(lua_State *L)
 {
@@ -156,7 +140,7 @@ static int meth_settimeout(lua_State *L) {
 
 
 /*-------------------------------------------------------------------------*\
-* Creates a serial object 
+* Creates a serial object
 \*-------------------------------------------------------------------------*/
 static int global_create(lua_State *L) {
     const char* path = luaL_checkstring(L, 1);
@@ -180,7 +164,7 @@ static int global_create(lua_State *L) {
     /* initialize remaining structure fields */
     socket_setnonblocking(&sock);
     un->sock = sock;
-    io_init(&un->io, (p_send) socket_write, (p_recv) socket_read, 
+    io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
             (p_error) socket_ioerror, &un->sock);
     timeout_init(&un->tm, -1, -1);
     buffer_init(&un->buf, &un->io, &un->tm);
diff --git a/src/socket.lua b/src/socket.lua
index 3913e6f..d1c0b16 100644
--- a/src/socket.lua
+++ b/src/socket.lua
@@ -32,23 +32,23 @@ function _M.bind(host, port, backlog)
     err = "no info on address"
     for i, alt in base.ipairs(addrinfo) do
         if alt.family == "inet" then
-            sock, err = socket.tcp()
+            sock, err = socket.tcp4()
         else
             sock, err = socket.tcp6()
         end
         if not sock then return nil, err end
         sock:setoption("reuseaddr", true)
         res, err = sock:bind(alt.addr, port)
-        if not res then 
+        if not res then
             sock:close()
-        else 
+        else
             res, err = sock:listen(backlog)
-            if not res then 
+            if not res then
                 sock:close()
             else
                 return sock
             end
-        end 
+        end
     end
     return nil, err
 end
diff --git a/src/tcp.c b/src/tcp.c
index 6594bda..ef9ee6f 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -6,6 +6,7 @@
 
 #include "lua.h"
 #include "lauxlib.h"
+#include "compat.h"
 
 #include "auxiliar.h"
 #include "socket.h"
@@ -17,6 +18,7 @@
 * Internal function prototypes
 \*=========================================================================*/
 static int global_create(lua_State *L);
+static int global_create4(lua_State *L);
 static int global_create6(lua_State *L);
 static int global_connect(lua_State *L);
 static int meth_connect(lua_State *L);
@@ -34,6 +36,7 @@ static int meth_accept(lua_State *L);
 static int meth_close(lua_State *L);
 static int meth_getoption(lua_State *L);
 static int meth_setoption(lua_State *L);
+static int meth_gettimeout(lua_State *L);
 static int meth_settimeout(lua_State *L);
 static int meth_getfd(lua_State *L);
 static int meth_setfd(lua_State *L);
@@ -63,6 +66,7 @@ static luaL_Reg tcp_methods[] = {
     {"setpeername", meth_connect},
     {"setsockname", meth_bind},
     {"settimeout",  meth_settimeout},
+    {"gettimeout",  meth_gettimeout},
     {"shutdown",    meth_shutdown},
     {NULL,          NULL}
 };
@@ -71,6 +75,7 @@ static luaL_Reg tcp_methods[] = {
 static t_opt optget[] = {
     {"keepalive",   opt_get_keepalive},
     {"reuseaddr",   opt_get_reuseaddr},
+    {"reuseport",   opt_get_reuseport},
     {"tcp-nodelay", opt_get_tcp_nodelay},
     {"linger",      opt_get_linger},
     {"error",       opt_get_error},
@@ -80,6 +85,7 @@ static t_opt optget[] = {
 static t_opt optset[] = {
     {"keepalive",   opt_set_keepalive},
     {"reuseaddr",   opt_set_reuseaddr},
+    {"reuseport",   opt_set_reuseport},
     {"tcp-nodelay", opt_set_tcp_nodelay},
     {"ipv6-v6only", opt_set_ip6_v6only},
     {"linger",      opt_set_linger},
@@ -89,6 +95,7 @@ static t_opt optset[] = {
 /* functions in library namespace */
 static luaL_Reg func[] = {
     {"tcp", global_create},
+    {"tcp4", global_create4},
     {"tcp6", global_create6},
     {"connect", global_connect},
     {NULL, NULL}
@@ -108,11 +115,7 @@ int tcp_open(lua_State *L)
     auxiliar_add2group(L, "tcp{client}", "tcp{any}");
     auxiliar_add2group(L, "tcp{server}", "tcp{any}");
     /* define library functions */
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
     luaL_setfuncs(L, func, 0);
-#else
-    luaL_openlib(L, NULL, func, 0);
-#endif
     return 0;
 }
 
@@ -216,8 +219,7 @@ static int meth_accept(lua_State *L)
 /*-------------------------------------------------------------------------*\
 * Binds an object to an address
 \*-------------------------------------------------------------------------*/
-static int meth_bind(lua_State *L)
-{
+static int meth_bind(lua_State *L) {
     p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1);
     const char *address =  luaL_checkstring(L, 2);
     const char *port = luaL_checkstring(L, 3);
@@ -227,7 +229,7 @@ static int meth_bind(lua_State *L)
     bindhints.ai_socktype = SOCK_STREAM;
     bindhints.ai_family = tcp->family;
     bindhints.ai_flags = AI_PASSIVE;
-    err = inet_trybind(&tcp->sock, address, port, &bindhints);
+    err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints);
     if (err) {
         lua_pushnil(L);
         lua_pushstring(L, err);
@@ -240,8 +242,7 @@ static int meth_bind(lua_State *L)
 /*-------------------------------------------------------------------------*\
 * Turns a master tcp object into a client object.
 \*-------------------------------------------------------------------------*/
-static int meth_connect(lua_State *L)
-{
+static int meth_connect(lua_State *L) {
     p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
     const char *address =  luaL_checkstring(L, 2);
     const char *port = luaL_checkstring(L, 3);
@@ -252,7 +253,7 @@ static int meth_connect(lua_State *L)
     /* make sure we try to connect only to the same family */
     connecthints.ai_family = tcp->family;
     timeout_markstart(&tcp->tm);
-    err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, 
+    err = inet_tryconnect(&tcp->sock, &tcp->family, address, port,
         &tcp->tm, &connecthints);
     /* have to set the class even if it failed due to non-blocking connects */
     auxiliar_setclass(L, "tcp{client}", 1);
@@ -282,9 +283,12 @@ static int meth_close(lua_State *L)
 static int meth_getfamily(lua_State *L)
 {
     p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
-    if (tcp->family == PF_INET6) {
+    if (tcp->family == AF_INET6) {
         lua_pushliteral(L, "inet6");
         return 1;
+    } else if (tcp->family == AF_INET) {
+        lua_pushliteral(L, "inet4");
+        return 1;
     } else {
         lua_pushliteral(L, "inet4");
         return 1;
@@ -348,6 +352,12 @@ static int meth_settimeout(lua_State *L)
     return timeout_meth_settimeout(L, &tcp->tm);
 }
 
+static int meth_gettimeout(lua_State *L)
+{
+    p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
+    return timeout_meth_gettimeout(L, &tcp->tm);
+}
+
 /*=========================================================================*\
 * Library functions
 \*=========================================================================*/
@@ -355,37 +365,36 @@ static int meth_settimeout(lua_State *L)
 * Creates a master tcp object
 \*-------------------------------------------------------------------------*/
 static int tcp_create(lua_State *L, int family) {
-    t_socket sock;
-    const char *err = inet_trycreate(&sock, family, SOCK_STREAM);
-    /* try to allocate a system socket */
-    if (!err) {
-        /* allocate tcp object */
-        p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
-        memset(tcp, 0, sizeof(t_tcp));
-        /* set its type as master object */
-        auxiliar_setclass(L, "tcp{master}", -1);
-        /* initialize remaining structure fields */
-        socket_setnonblocking(&sock);
-        if (family == PF_INET6) {
-            int yes = 1;
-            setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
-                (void *)&yes, sizeof(yes));
+    p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
+    memset(tcp, 0, sizeof(t_tcp));
+    /* set its type as master object */
+    auxiliar_setclass(L, "tcp{master}", -1);
+    /* if family is AF_UNSPEC, we leave the socket invalid and
+     * store AF_UNSPEC into family. This will allow it to later be
+     * replaced with an AF_INET6 or AF_INET socket upon first use. */
+    tcp->sock = SOCKET_INVALID;
+    tcp->family = family;
+    io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
+            (p_error) socket_ioerror, &tcp->sock);
+    timeout_init(&tcp->tm, -1, -1);
+    buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
+    if (family != AF_UNSPEC) {
+        const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0);
+        if (err != NULL) {
+            lua_pushnil(L);
+            lua_pushstring(L, err);
+            return 2;
         }
-        tcp->sock = sock;
-        io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
-                (p_error) socket_ioerror, &tcp->sock);
-        timeout_init(&tcp->tm, -1, -1);
-        buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
-        tcp->family = family;
-        return 1;
-    } else {
-        lua_pushnil(L);
-        lua_pushstring(L, err);
-        return 2;
+        socket_setnonblocking(&tcp->sock);
     }
+    return 1;
 }
 
 static int global_create(lua_State *L) {
+    return tcp_create(L, AF_UNSPEC);
+}
+
+static int global_create4(lua_State *L) {
     return tcp_create(L, AF_INET);
 }
 
@@ -393,53 +402,6 @@ static int global_create6(lua_State *L) {
     return tcp_create(L, AF_INET6);
 }
 
-#if 0
-static const char *tryconnect6(const char *remoteaddr, const char *remoteserv,
-    struct addrinfo *connecthints, p_tcp tcp) {
-    struct addrinfo *iterator = NULL, *resolved = NULL;
-    const char *err = NULL;
-    /* try resolving */
-    err = socket_gaistrerror(getaddrinfo(remoteaddr, remoteserv,
-                connecthints, &resolved));
-    if (err != NULL) {
-        if (resolved) freeaddrinfo(resolved);
-        return err;
-    }
-    /* iterate over all returned addresses trying to connect */
-    for (iterator = resolved; iterator; iterator = iterator->ai_next) {
-        p_timeout tm = timeout_markstart(&tcp->tm);
-        /* create new socket if necessary. if there was no
-         * bind, we need to create one for every new family
-         * that shows up while iterating. if there was a
-         * bind, all families will be the same and we will
-         * not enter this branch. */
-        if (tcp->family != iterator->ai_family) {
-            socket_destroy(&tcp->sock);
-            err = socket_strerror(socket_create(&tcp->sock,
-                iterator->ai_family, iterator->ai_socktype,
-                iterator->ai_protocol));
-            if (err != NULL) {
-                freeaddrinfo(resolved);
-                return err;
-            }
-            tcp->family = iterator->ai_family;
-            /* all sockets initially non-blocking */
-            socket_setnonblocking(&tcp->sock);
-        }
-        /* finally try connecting to remote address */
-        err = socket_strerror(socket_connect(&tcp->sock,
-            (SA *) iterator->ai_addr,
-            (socklen_t) iterator->ai_addrlen, tm));
-        /* if success, break out of loop */
-        if (err == NULL) break;
-    }
-
-    freeaddrinfo(resolved);
-    /* here, if err is set, we failed */
-    return err;
-}
-#endif
-
 static int global_connect(lua_State *L) {
     const char *remoteaddr = luaL_checkstring(L, 1);
     const char *remoteserv = luaL_checkstring(L, 2);
@@ -456,26 +418,26 @@ static int global_connect(lua_State *L) {
     timeout_init(&tcp->tm, -1, -1);
     buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
     tcp->sock = SOCKET_INVALID;
-    tcp->family = PF_UNSPEC;
+    tcp->family = AF_UNSPEC;
     /* allow user to pick local address and port */
     memset(&bindhints, 0, sizeof(bindhints));
     bindhints.ai_socktype = SOCK_STREAM;
     bindhints.ai_family = family;
     bindhints.ai_flags = AI_PASSIVE;
     if (localaddr) {
-        err = inet_trybind(&tcp->sock, localaddr, localserv, &bindhints);
+        err = inet_trybind(&tcp->sock, &tcp->family, localaddr,
+            localserv, &bindhints);
         if (err) {
             lua_pushnil(L);
             lua_pushstring(L, err);
             return 2;
         }
-        tcp->family = bindhints.ai_family;
     }
     /* try to connect to remote address and port */
     memset(&connecthints, 0, sizeof(connecthints));
     connecthints.ai_socktype = SOCK_STREAM;
     /* make sure we try to connect only to the same family */
-    connecthints.ai_family = bindhints.ai_family;
+    connecthints.ai_family = tcp->family;
     err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv,
          &tcp->tm, &connecthints);
     if (err) {
diff --git a/src/timeout.c b/src/timeout.c
index bdd5e1c..5a601d5 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -8,6 +8,7 @@
 
 #include "lua.h"
 #include "lauxlib.h"
+#include "compat.h"
 
 #include "auxiliar.h"
 #include "timeout.h"
@@ -52,7 +53,7 @@ void timeout_init(p_timeout tm, double block, double total) {
 
 /*-------------------------------------------------------------------------*\
 * Determines how much time we have left for the next system call,
-* if the previous call was successful 
+* if the previous call was successful
 * Input
 *   tm: timeout control structure
 * Returns
@@ -107,7 +108,7 @@ double timeout_getretry(p_timeout tm) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Marks the operation start time in structure 
+* Marks the operation start time in structure
 * Input
 *   tm: timeout control structure
 \*-------------------------------------------------------------------------*/
@@ -117,7 +118,7 @@ p_timeout timeout_markstart(p_timeout tm) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Gets time in s, relative to January 1, 1970 (UTC) 
+* Gets time in s, relative to January 1, 1970 (UTC)
 * Returns
 *   time in s.
 \*-------------------------------------------------------------------------*/
@@ -144,11 +145,7 @@ double timeout_gettime(void) {
 * Initializes module
 \*-------------------------------------------------------------------------*/
 int timeout_open(lua_State *L) {
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
     luaL_setfuncs(L, func, 0);
-#else
-    luaL_openlib(L, NULL, func, 0);
-#endif
     return 0;
 }
 
@@ -163,7 +160,7 @@ int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
     const char *mode = luaL_optstring(L, 3, "b");
     switch (*mode) {
         case 'b':
-            tm->block = t; 
+            tm->block = t;
             break;
         case 'r': case 't':
             tm->total = t;
@@ -176,6 +173,16 @@ int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
     return 1;
 }
 
+/*-------------------------------------------------------------------------*\
+* Gets timeout values for IO operations
+* Lua Output: block, total
+\*-------------------------------------------------------------------------*/
+int timeout_meth_gettimeout(lua_State *L, p_timeout tm) {
+    lua_pushnumber(L, tm->block);
+    lua_pushnumber(L, tm->total);
+    return 2;
+}
+
 /*=========================================================================*\
 * Test support functions
 \*=========================================================================*/
diff --git a/src/timeout.h b/src/timeout.h
index 6715ca7..af90231 100644
--- a/src/timeout.h
+++ b/src/timeout.h
@@ -22,6 +22,7 @@ p_timeout timeout_markstart(p_timeout tm);
 double timeout_getstart(p_timeout tm);
 double timeout_gettime(void);
 int timeout_meth_settimeout(lua_State *L, p_timeout tm);
+int timeout_meth_gettimeout(lua_State *L, p_timeout tm);
 
 #define timeout_iszero(tm)   ((tm)->block == 0.0)
 
diff --git a/src/tp.lua b/src/tp.lua
index cbeff56..328cbab 100644
--- a/src/tp.lua
+++ b/src/tp.lua
@@ -74,7 +74,7 @@ function metat.__index:command(cmd, arg)
 end
 
 function metat.__index:sink(snk, pat)
-    local chunk, err = c:receive(pat)
+    local chunk, err = self.c:receive(pat)
     return snk(chunk, err)
 end
 
diff --git a/src/udp.c b/src/udp.c
index a9f2393..ec97252 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -7,6 +7,7 @@
 
 #include "lua.h"
 #include "lauxlib.h"
+#include "compat.h"
 
 #include "auxiliar.h"
 #include "socket.h"
@@ -26,6 +27,7 @@
 * Internal function prototypes
 \*=========================================================================*/
 static int global_create(lua_State *L);
+static int global_create4(lua_State *L);
 static int global_create6(lua_State *L);
 static int meth_send(lua_State *L);
 static int meth_sendto(lua_State *L);
@@ -34,6 +36,7 @@ static int meth_receivefrom(lua_State *L);
 static int meth_getfamily(lua_State *L);
 static int meth_getsockname(lua_State *L);
 static int meth_getpeername(lua_State *L);
+static int meth_gettimeout(lua_State *L);
 static int meth_setsockname(lua_State *L);
 static int meth_setpeername(lua_State *L);
 static int meth_close(lua_State *L);
@@ -64,6 +67,7 @@ static luaL_Reg udp_methods[] = {
     {"setpeername", meth_setpeername},
     {"setsockname", meth_setsockname},
     {"settimeout",  meth_settimeout},
+    {"gettimeout",  meth_gettimeout},
     {NULL,          NULL}
 };
 
@@ -89,6 +93,10 @@ static t_opt optset[] = {
 
 /* socket options for getoption */
 static t_opt optget[] = {
+    {"dontroute",            opt_get_dontroute},
+    {"broadcast",            opt_get_broadcast},
+    {"reuseaddr",            opt_get_reuseaddr},
+    {"reuseport",            opt_get_reuseport},
     {"ip-multicast-if",      opt_get_ip_multicast_if},
     {"ip-multicast-loop",    opt_get_ip_multicast_loop},
     {"error",                opt_get_error},
@@ -102,6 +110,7 @@ static t_opt optget[] = {
 /* functions in library namespace */
 static luaL_Reg func[] = {
     {"udp", global_create},
+    {"udp4", global_create4},
     {"udp6", global_create6},
     {NULL, NULL}
 };
@@ -109,8 +118,7 @@ static luaL_Reg func[] = {
 /*-------------------------------------------------------------------------*\
 * Initializes module
 \*-------------------------------------------------------------------------*/
-int udp_open(lua_State *L)
-{
+int udp_open(lua_State *L) {
     /* create classes */
     auxiliar_newclass(L, "udp{connected}", udp_methods);
     auxiliar_newclass(L, "udp{unconnected}", udp_methods);
@@ -120,18 +128,18 @@ int udp_open(lua_State *L)
     auxiliar_add2group(L, "udp{connected}",   "select{able}");
     auxiliar_add2group(L, "udp{unconnected}", "select{able}");
     /* define library functions */
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
     luaL_setfuncs(L, func, 0);
-#else
-    luaL_openlib(L, NULL, func, 0);
-#endif
+    /* export default UDP size */
+    lua_pushliteral(L, "_DATAGRAMSIZE");
+    lua_pushinteger(L, UDP_DATAGRAMSIZE);
+    lua_rawset(L, -3);
     return 0;
 }
 
 /*=========================================================================*\
 * Lua methods
 \*=========================================================================*/
-const char *udp_strerror(int err) {
+static const char *udp_strerror(int err) {
     /* a 'closed' error on an unconnected means the target address was not
      * accepted by the transport layer */
     if (err == IO_CLOSED) return "refused";
@@ -182,7 +190,7 @@ static int meth_sendto(lua_State *L) {
         return 2;
     }
     timeout_markstart(tm);
-    err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, 
+    err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
         (socklen_t) ai->ai_addrlen, tm);
     freeaddrinfo(ai);
     if (err != IO_DONE) {
@@ -199,71 +207,80 @@ static int meth_sendto(lua_State *L) {
 \*-------------------------------------------------------------------------*/
 static int meth_receive(lua_State *L) {
     p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
-    char buffer[UDP_DATAGRAMSIZE];
-    size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
+    char buf[UDP_DATAGRAMSIZE];
+    size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
+    char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
     int err;
     p_timeout tm = &udp->tm;
-    count = MIN(count, sizeof(buffer));
     timeout_markstart(tm);
-    err = socket_recv(&udp->sock, buffer, count, &got, tm);
+    if (!dgram) {
+        lua_pushnil(L);
+        lua_pushliteral(L, "out of memory");
+        return 2;
+    }
+    err = socket_recv(&udp->sock, dgram, wanted, &got, tm);
     /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
-    if (err == IO_CLOSED)
-        err = IO_DONE;
-    if (err != IO_DONE) {
+    if (err != IO_DONE && err != IO_CLOSED) {
         lua_pushnil(L);
         lua_pushstring(L, udp_strerror(err));
+        if (wanted > sizeof(buf)) free(dgram);
         return 2;
     }
-    lua_pushlstring(L, buffer, got);
+    lua_pushlstring(L, dgram, got);
+    if (wanted > sizeof(buf)) free(dgram);
     return 1;
 }
 
 /*-------------------------------------------------------------------------*\
 * Receives data and sender from a UDP socket
 \*-------------------------------------------------------------------------*/
-static int meth_receivefrom(lua_State *L)
-{
+static int meth_receivefrom(lua_State *L) {
     p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
-    char buffer[UDP_DATAGRAMSIZE];
-    size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
-    int err;
-    p_timeout tm = &udp->tm;
+    char buf[UDP_DATAGRAMSIZE];
+    size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
+    char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
     struct sockaddr_storage addr;
     socklen_t addr_len = sizeof(addr);
     char addrstr[INET6_ADDRSTRLEN];
     char portstr[6];
+    int err;
+    p_timeout tm = &udp->tm;
     timeout_markstart(tm);
-    count = MIN(count, sizeof(buffer));
-    err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, 
+    if (!dgram) {
+        lua_pushnil(L);
+        lua_pushliteral(L, "out of memory");
+        return 2;
+    }
+    err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr,
             &addr_len, tm);
     /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
-    if (err == IO_CLOSED)
-        err = IO_DONE;
-    if (err != IO_DONE) {
+    if (err != IO_DONE && err != IO_CLOSED) {
         lua_pushnil(L);
         lua_pushstring(L, udp_strerror(err));
+        if (wanted > sizeof(buf)) free(dgram);
         return 2;
     }
-    err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, 
+    err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
         INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
 	if (err) {
         lua_pushnil(L);
         lua_pushstring(L, gai_strerror(err));
+        if (wanted > sizeof(buf)) free(dgram);
         return 2;
     }
-    lua_pushlstring(L, buffer, got);
+    lua_pushlstring(L, dgram, got);
     lua_pushstring(L, addrstr);
     lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10));
+    if (wanted > sizeof(buf)) free(dgram);
     return 3;
 }
 
 /*-------------------------------------------------------------------------*\
 * Returns family as string
 \*-------------------------------------------------------------------------*/
-static int meth_getfamily(lua_State *L)
-{
+static int meth_getfamily(lua_State *L) {
     p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
-    if (udp->family == PF_INET6) {
+    if (udp->family == AF_INET6) {
         lua_pushliteral(L, "inet6");
         return 1;
     } else {
@@ -332,6 +349,11 @@ static int meth_settimeout(lua_State *L) {
     return timeout_meth_settimeout(L, &udp->tm);
 }
 
+static int meth_gettimeout(lua_State *L) {
+    p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
+    return timeout_meth_gettimeout(L, &udp->tm);
+}
+
 /*-------------------------------------------------------------------------*\
 * Turns a master udp object into a client object.
 \*-------------------------------------------------------------------------*/
@@ -348,7 +370,7 @@ static int meth_setpeername(lua_State *L) {
     /* make sure we try to connect only to the same family */
     connecthints.ai_family = udp->family;
     if (connecting) {
-        err = inet_tryconnect(&udp->sock, &udp->family, address, 
+        err = inet_tryconnect(&udp->sock, &udp->family, address,
             port, tm, &connecthints);
         if (err) {
             lua_pushnil(L);
@@ -362,7 +384,6 @@ static int meth_setpeername(lua_State *L) {
         inet_trydisconnect(&udp->sock, udp->family, tm);
         auxiliar_setclass(L, "udp{unconnected}", 1);
     }
-    /* change class to connected or unconnected depending on address */
     lua_pushnumber(L, 1);
     return 1;
 }
@@ -390,7 +411,7 @@ static int meth_setsockname(lua_State *L) {
     bindhints.ai_socktype = SOCK_DGRAM;
     bindhints.ai_family = udp->family;
     bindhints.ai_flags = AI_PASSIVE;
-    err = inet_trybind(&udp->sock, address, port, &bindhints);
+    err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints);
     if (err) {
         lua_pushnil(L);
         lua_pushstring(L, err);
@@ -407,32 +428,32 @@ static int meth_setsockname(lua_State *L) {
 * Creates a master udp object
 \*-------------------------------------------------------------------------*/
 static int udp_create(lua_State *L, int family) {
-    t_socket sock;
-    const char *err = inet_trycreate(&sock, family, SOCK_DGRAM);
-    /* try to allocate a system socket */
-    if (!err) {
-        /* allocate udp object */
-        p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
-        auxiliar_setclass(L, "udp{unconnected}", -1);
-        /* initialize remaining structure fields */
-        socket_setnonblocking(&sock);
-        if (family == PF_INET6) {
-            int yes = 1;
-            setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
-                (void *)&yes, sizeof(yes));
+    /* allocate udp object */
+    p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
+    auxiliar_setclass(L, "udp{unconnected}", -1);
+    /* if family is AF_UNSPEC, we leave the socket invalid and
+     * store AF_UNSPEC into family. This will allow it to later be
+     * replaced with an AF_INET6 or AF_INET socket upon first use. */
+    udp->sock = SOCKET_INVALID;
+    timeout_init(&udp->tm, -1, -1);
+    udp->family = family;
+    if (family != AF_UNSPEC) {
+        const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0);
+        if (err != NULL) {
+            lua_pushnil(L);
+            lua_pushstring(L, err);
+            return 2;
         }
-        udp->sock = sock;
-        timeout_init(&udp->tm, -1, -1);
-        udp->family = family;
-        return 1;
-    } else {
-        lua_pushnil(L);
-        lua_pushstring(L, err);
-        return 2;
+        socket_setnonblocking(&udp->sock);
     }
+    return 1;
 }
 
 static int global_create(lua_State *L) {
+    return udp_create(L, AF_UNSPEC);
+}
+
+static int global_create4(lua_State *L) {
     return udp_create(L, AF_INET);
 }
 
diff --git a/src/udp.h b/src/udp.h
index 2b831a5..be9b6a5 100644
--- a/src/udp.h
+++ b/src/udp.h
@@ -8,7 +8,7 @@
 * (AF_INET, SOCK_DGRAM).
 *
 * Two classes are defined: connected and unconnected. UDP objects are
-* originally unconnected. They can be "connected" to a given address 
+* originally unconnected. They can be "connected" to a given address
 * with a call to the setpeername function. The same function can be used to
 * break the connection.
 \*=========================================================================*/
@@ -17,7 +17,6 @@
 #include "timeout.h"
 #include "socket.h"
 
-/* can't be larger than wsocket.c MAXCHUNK!!! */
 #define UDP_DATAGRAMSIZE 8192
 
 typedef struct t_udp_ {
diff --git a/src/unix.c b/src/unix.c
index 91aaaf8..5bc3148 100644
--- a/src/unix.c
+++ b/src/unix.c
@@ -1,8 +1,8 @@
 /*=========================================================================*\
-* Unix domain socket 
+* Unix domain socket
 * LuaSocket toolkit
 \*=========================================================================*/
-#include <string.h> 
+#include <string.h>
 
 #include "lua.h"
 #include "lauxlib.h"
@@ -11,7 +11,7 @@
 #include "socket.h"
 #include "options.h"
 #include "unix.h"
-#include <sys/un.h> 
+#include <sys/un.h>
 
 /*=========================================================================*\
 * Internal function prototypes
@@ -68,15 +68,6 @@ static t_opt optset[] = {
     {NULL,          NULL}
 };
 
-/* our socket creation function */
-/* this is an ad-hoc module that returns a single function 
- * as such, do not include other functions in this array. */
-static luaL_Reg func[] = {
-    {"unix", global_create},
-    {NULL,          NULL}
-};
-
-
 /*-------------------------------------------------------------------------*\
 * Initializes module
 \*-------------------------------------------------------------------------*/
@@ -89,15 +80,8 @@ int luaopen_socket_unix(lua_State *L) {
     auxiliar_add2group(L, "unix{master}", "unix{any}");
     auxiliar_add2group(L, "unix{client}", "unix{any}");
     auxiliar_add2group(L, "unix{server}", "unix{any}");
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
-    lua_pushcfunction(L, global_create);
-    (void) func;
-#else
-    /* set function into socket namespace */
-    luaL_openlib(L, "socket", func, 0);
-    lua_pushcfunction(L, global_create);
-#endif
     /* return the function instead of the 'socket' table */
+    lua_pushcfunction(L, global_create);
     return 1;
 }
 
@@ -147,7 +131,7 @@ static int meth_getfd(lua_State *L) {
 /* this is very dangerous, but can be handy for those that are brave enough */
 static int meth_setfd(lua_State *L) {
     p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
-    un->sock = (t_socket) luaL_checknumber(L, 2); 
+    un->sock = (t_socket) luaL_checknumber(L, 2);
     return 0;
 }
 
@@ -158,8 +142,8 @@ static int meth_dirty(lua_State *L) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Waits for and returns a client object attempting connection to the 
-* server object 
+* Waits for and returns a client object attempting connection to the
+* server object
 \*-------------------------------------------------------------------------*/
 static int meth_accept(lua_State *L) {
     p_unix server = (p_unix) auxiliar_checkclass(L, "unix{server}", 1);
@@ -173,20 +157,20 @@ static int meth_accept(lua_State *L) {
         /* initialize structure fields */
         socket_setnonblocking(&sock);
         clnt->sock = sock;
-        io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv, 
+        io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
                 (p_error) socket_ioerror, &clnt->sock);
         timeout_init(&clnt->tm, -1, -1);
         buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
         return 1;
     } else {
-        lua_pushnil(L); 
+        lua_pushnil(L);
         lua_pushstring(L, socket_strerror(err));
         return 2;
     }
 }
 
 /*-------------------------------------------------------------------------*\
-* Binds an object to an address 
+* Binds an object to an address
 \*-------------------------------------------------------------------------*/
 static const char *unix_trybind(p_unix un, const char *path) {
     struct sockaddr_un local;
@@ -197,16 +181,16 @@ static const char *unix_trybind(p_unix un, const char *path) {
     strcpy(local.sun_path, path);
     local.sun_family = AF_UNIX;
 #ifdef UNIX_HAS_SUN_LEN
-    local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) 
+    local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
         + len + 1;
     err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
 
-#else 
-    err = socket_bind(&un->sock, (SA *) &local, 
+#else
+    err = socket_bind(&un->sock, (SA *) &local,
             sizeof(local.sun_family) + len);
 #endif
     if (err != IO_DONE) socket_destroy(&un->sock);
-    return socket_strerror(err); 
+    return socket_strerror(err);
 }
 
 static int meth_bind(lua_State *L) {
@@ -236,11 +220,11 @@ static const char *unix_tryconnect(p_unix un, const char *path)
     remote.sun_family = AF_UNIX;
     timeout_markstart(&un->tm);
 #ifdef UNIX_HAS_SUN_LEN
-    remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) 
+    remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
         + len + 1;
     err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
 #else
-    err = socket_connect(&un->sock, (SA *) &remote, 
+    err = socket_connect(&un->sock, (SA *) &remote,
             sizeof(remote.sun_family) + len, &un->tm);
 #endif
     if (err != IO_DONE) socket_destroy(&un->sock);
@@ -264,7 +248,7 @@ static int meth_connect(lua_State *L)
 }
 
 /*-------------------------------------------------------------------------*\
-* Closes socket used by object 
+* Closes socket used by object
 \*-------------------------------------------------------------------------*/
 static int meth_close(lua_State *L)
 {
@@ -319,13 +303,13 @@ static int meth_settimeout(lua_State *L) {
 * Library functions
 \*=========================================================================*/
 /*-------------------------------------------------------------------------*\
-* Creates a master unix object 
+* Creates a master unix object
 \*-------------------------------------------------------------------------*/
 static int global_create(lua_State *L) {
     t_socket sock;
     int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
     /* try to allocate a system socket */
-    if (err == IO_DONE) { 
+    if (err == IO_DONE) {
         /* allocate unix object */
         p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
         /* set its type as master object */
@@ -333,7 +317,7 @@ static int global_create(lua_State *L) {
         /* initialize remaining structure fields */
         socket_setnonblocking(&sock);
         un->sock = sock;
-        io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv, 
+        io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
                 (p_error) socket_ioerror, &un->sock);
         timeout_init(&un->tm, -1, -1);
         buffer_init(&un->buf, &un->io, &un->tm);
diff --git a/src/url.lua b/src/url.lua
index 7809535..fbd93d1 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -219,6 +219,7 @@ end
 --   corresponding absolute url
 -----------------------------------------------------------------------------
 function _M.absolute(base_url, relative_url)
+    local base_parsed
     if base.type(base_url) == "table" then
         base_parsed = base_url
         base_url = _M.build(base_parsed)
diff --git a/src/usocket.c b/src/usocket.c
index 096ecd0..8adc573 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -4,12 +4,13 @@
 *
 * The code is now interrupt-safe.
 * The penalty of calling select to avoid busy-wait is only paid when
-* the I/O call fail in the first place. 
+* the I/O call fail in the first place.
 \*=========================================================================*/
-#include <string.h> 
+#include <string.h>
 #include <signal.h>
 
 #include "socket.h"
+#include "pierror.h"
 
 /*-------------------------------------------------------------------------*\
 * Wait for readable/writable/connected socket with timeout
@@ -72,7 +73,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
 
 
 /*-------------------------------------------------------------------------*\
-* Initializes module 
+* Initializes module
 \*-------------------------------------------------------------------------*/
 int socket_open(void) {
     /* instals a handler to ignore sigpipe or it will crash us */
@@ -81,7 +82,7 @@ int socket_open(void) {
 }
 
 /*-------------------------------------------------------------------------*\
-* Close module 
+* Close module
 \*-------------------------------------------------------------------------*/
 int socket_close(void) {
     return 1;
@@ -92,7 +93,6 @@ int socket_close(void) {
 \*-------------------------------------------------------------------------*/
 void socket_destroy(p_socket ps) {
     if (*ps != SOCKET_INVALID) {
-        socket_setblocking(ps);
         close(*ps);
         *ps = SOCKET_INVALID;
     }
@@ -101,7 +101,7 @@ void socket_destroy(p_socket ps) {
 /*-------------------------------------------------------------------------*\
 * Select with timeout control
 \*-------------------------------------------------------------------------*/
-int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, 
+int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
         p_timeout tm) {
     int ret;
     do {
@@ -120,8 +120,8 @@ int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
 \*-------------------------------------------------------------------------*/
 int socket_create(p_socket ps, int domain, int type, int protocol) {
     *ps = socket(domain, type, protocol);
-    if (*ps != SOCKET_INVALID) return IO_DONE; 
-    else return errno; 
+    if (*ps != SOCKET_INVALID) return IO_DONE;
+    else return errno;
 }
 
 /*-------------------------------------------------------------------------*\
@@ -130,29 +130,25 @@ int socket_create(p_socket ps, int domain, int type, int protocol) {
 int socket_bind(p_socket ps, SA *addr, socklen_t len) {
     int err = IO_DONE;
     socket_setblocking(ps);
-    if (bind(*ps, addr, len) < 0) err = errno; 
+    if (bind(*ps, addr, len) < 0) err = errno;
     socket_setnonblocking(ps);
     return err;
 }
 
 /*-------------------------------------------------------------------------*\
-* 
+*
 \*-------------------------------------------------------------------------*/
 int socket_listen(p_socket ps, int backlog) {
-    int err = IO_DONE; 
-    socket_setblocking(ps);
-    if (listen(*ps, backlog)) err = errno; 
-    socket_setnonblocking(ps);
+    int err = IO_DONE;
+    if (listen(*ps, backlog)) err = errno;
     return err;
 }
 
 /*-------------------------------------------------------------------------*\
-* 
+*
 \*-------------------------------------------------------------------------*/
 void socket_shutdown(p_socket ps, int how) {
-    socket_setblocking(ps);
     shutdown(*ps, how);
-    socket_setnonblocking(ps);
 }
 
 /*-------------------------------------------------------------------------*\
@@ -166,7 +162,7 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
     do if (connect(*ps, addr, len) == 0) return IO_DONE;
     while ((err = errno) == EINTR);
     /* if connection failed immediately, return error code */
-    if (err != EINPROGRESS && err != EAGAIN) return err; 
+    if (err != EINPROGRESS && err != EAGAIN) return err;
     /* zero timeout case optimization */
     if (timeout_iszero(tm)) return IO_TIMEOUT;
     /* wait until we have the result of the connection attempt or timeout */
@@ -181,7 +177,7 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
 * Accept with timeout
 \*-------------------------------------------------------------------------*/
 int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) {
-    if (*ps == SOCKET_INVALID) return IO_CLOSED; 
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
     for ( ;; ) {
         int err;
         if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
@@ -197,7 +193,7 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout
 /*-------------------------------------------------------------------------*\
 * Send with timeout
 \*-------------------------------------------------------------------------*/
-int socket_send(p_socket ps, const char *data, size_t count, 
+int socket_send(p_socket ps, const char *data, size_t count,
         size_t *sent, p_timeout tm)
 {
     int err;
@@ -215,6 +211,8 @@ int socket_send(p_socket ps, const char *data, size_t count,
         err = errno;
         /* EPIPE means the connection was closed */
         if (err == EPIPE) return IO_CLOSED;
+        /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/
+        if (err == EPROTOTYPE) continue;
         /* we call was interrupted, just try again */
         if (err == EINTR) continue;
         /* if failed fatal reason, report error */
@@ -229,20 +227,21 @@ int socket_send(p_socket ps, const char *data, size_t count,
 /*-------------------------------------------------------------------------*\
 * Sendto with timeout
 \*-------------------------------------------------------------------------*/
-int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, 
+int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
         SA *addr, socklen_t len, p_timeout tm)
 {
     int err;
     *sent = 0;
     if (*ps == SOCKET_INVALID) return IO_CLOSED;
     for ( ;; ) {
-        long put = (long) sendto(*ps, data, count, 0, addr, len);  
+        long put = (long) sendto(*ps, data, count, 0, addr, len); 
         if (put >= 0) {
             *sent = put;
             return IO_DONE;
         }
         err = errno;
         if (err == EPIPE) return IO_CLOSED;
+        if (err == EPROTOTYPE) continue;
         if (err == EINTR) continue;
         if (err != EAGAIN) return err;
         if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
@@ -266,8 +265,8 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm
         err = errno;
         if (taken == 0) return IO_CLOSED;
         if (err == EINTR) continue;
-        if (err != EAGAIN) return err; 
-        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; 
+        if (err != EAGAIN) return err;
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
     }
     return IO_UNKNOWN;
 }
@@ -275,7 +274,7 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm
 /*-------------------------------------------------------------------------*\
 * Recvfrom with timeout
 \*-------------------------------------------------------------------------*/
-int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, 
+int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
         SA *addr, socklen_t *len, p_timeout tm) {
     int err;
     *got = 0;
@@ -289,8 +288,8 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
         err = errno;
         if (taken == 0) return IO_CLOSED;
         if (err == EINTR) continue;
-        if (err != EAGAIN) return err; 
-        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; 
+        if (err != EAGAIN) return err;
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
     }
     return IO_UNKNOWN;
 }
@@ -303,7 +302,7 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
 * with send/recv replaced with write/read. We can't just use write/read
 * in the socket version, because behaviour when size is zero is different.
 \*-------------------------------------------------------------------------*/
-int socket_write(p_socket ps, const char *data, size_t count, 
+int socket_write(p_socket ps, const char *data, size_t count,
         size_t *sent, p_timeout tm)
 {
     int err;
@@ -321,6 +320,8 @@ int socket_write(p_socket ps, const char *data, size_t count,
         err = errno;
         /* EPIPE means the connection was closed */
         if (err == EPIPE) return IO_CLOSED;
+        /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/
+        if (err == EPROTOTYPE) continue;
         /* we call was interrupted, just try again */
         if (err == EINTR) continue;
         /* if failed fatal reason, report error */
@@ -349,8 +350,8 @@ int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm
         err = errno;
         if (taken == 0) return IO_CLOSED;
         if (err == EINTR) continue;
-        if (err != EAGAIN) return err; 
-        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; 
+        if (err != EAGAIN) return err;
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
     }
     return IO_UNKNOWN;
 }
@@ -374,7 +375,7 @@ void socket_setnonblocking(p_socket ps) {
 }
 
 /*-------------------------------------------------------------------------*\
-* DNS helpers 
+* DNS helpers
 \*-------------------------------------------------------------------------*/
 int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
     *hp = gethostbyaddr(addr, len, AF_INET);
@@ -399,7 +400,7 @@ int socket_gethostbyname(const char *addr, struct hostent **hp) {
 const char *socket_hoststrerror(int err) {
     if (err <= 0) return io_strerror(err);
     switch (err) {
-        case HOST_NOT_FOUND: return "host not found";
+        case HOST_NOT_FOUND: return PIE_HOST_NOT_FOUND;
         default: return hstrerror(err);
     }
 }
@@ -407,42 +408,43 @@ const char *socket_hoststrerror(int err) {
 const char *socket_strerror(int err) {
     if (err <= 0) return io_strerror(err);
     switch (err) {
-        case EADDRINUSE: return "address already in use";
-        case EISCONN: return "already connected";
-        case EACCES: return "permission denied";
-        case ECONNREFUSED: return "connection refused";
-        case ECONNABORTED: return "closed";
-        case ECONNRESET: return "closed";
-        case ETIMEDOUT: return "timeout";
-        default: return strerror(err);
+        case EADDRINUSE: return PIE_ADDRINUSE;
+        case EISCONN: return PIE_ISCONN;
+        case EACCES: return PIE_ACCESS;
+        case ECONNREFUSED: return PIE_CONNREFUSED;
+        case ECONNABORTED: return PIE_CONNABORTED;
+        case ECONNRESET: return PIE_CONNRESET;
+        case ETIMEDOUT: return PIE_TIMEDOUT;
+        default: {
+            return strerror(err);
+        }
     }
 }
 
 const char *socket_ioerror(p_socket ps, int err) {
     (void) ps;
     return socket_strerror(err);
-} 
+}
 
 const char *socket_gaistrerror(int err) {
-    if (err == 0) return NULL; 
+    if (err == 0) return NULL;
     switch (err) {
-        case EAI_AGAIN: return "temporary failure in name resolution";
-        case EAI_BADFLAGS: return "invalid value for ai_flags";
+        case EAI_AGAIN: return PIE_AGAIN;
+        case EAI_BADFLAGS: return PIE_BADFLAGS;
 #ifdef EAI_BADHINTS
-        case EAI_BADHINTS: return "invalid value for hints";
+        case EAI_BADHINTS: return PIE_BADHINTS;
 #endif
-        case EAI_FAIL: return "non-recoverable failure in name resolution";
-        case EAI_FAMILY: return "ai_family not supported";
-        case EAI_MEMORY: return "memory allocation failure";
-        case EAI_NONAME: 
-            return "host or service not provided, or not known";
-        case EAI_OVERFLOW: return "argument buffer overflow";
+        case EAI_FAIL: return PIE_FAIL;
+        case EAI_FAMILY: return PIE_FAMILY;
+        case EAI_MEMORY: return PIE_MEMORY;
+        case EAI_NONAME: return PIE_NONAME;
+        case EAI_OVERFLOW: return PIE_OVERFLOW;
 #ifdef EAI_PROTOCOL
-        case EAI_PROTOCOL: return "resolved protocol is unknown";
+        case EAI_PROTOCOL: return PIE_PROTOCOL;
 #endif
-        case EAI_SERVICE: return "service not supported for socket type";
-        case EAI_SOCKTYPE: return "ai_socktype not supported";
-        case EAI_SYSTEM: return strerror(errno); 
+        case EAI_SERVICE: return PIE_SERVICE;
+        case EAI_SOCKTYPE: return PIE_SOCKTYPE;
+        case EAI_SYSTEM: return strerror(errno);
         default: return gai_strerror(err);
     }
 }
diff --git a/src/wsocket.c b/src/wsocket.c
index b4a4384..8ecb0fc 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -3,33 +3,34 @@
 * LuaSocket toolkit
 *
 * The penalty of calling select to avoid busy-wait is only paid when
-* the I/O call fail in the first place. 
+* the I/O call fail in the first place.
 \*=========================================================================*/
 #include <string.h>
 
 #include "socket.h"
+#include "pierror.h"
 
 /* WinSock doesn't have a strerror... */
 static const char *wstrerror(int err);
 
 /*-------------------------------------------------------------------------*\
-* Initializes module 
+* Initializes module
 \*-------------------------------------------------------------------------*/
 int socket_open(void) {
     WSADATA wsaData;
-    WORD wVersionRequested = MAKEWORD(2, 0); 
+    WORD wVersionRequested = MAKEWORD(2, 0);
     int err = WSAStartup(wVersionRequested, &wsaData );
     if (err != 0) return 0;
     if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) &&
         (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) {
         WSACleanup();
-        return 0; 
+        return 0;
     }
     return 1;
 }
 
 /*-------------------------------------------------------------------------*\
-* Close module 
+* Close module
 \*-------------------------------------------------------------------------*/
 int socket_close(void) {
     WSACleanup();
@@ -50,10 +51,10 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
     struct timeval tv, *tp = NULL;
     double t;
     if (timeout_iszero(tm)) return IO_TIMEOUT;  /* optimize timeout == 0 case */
-    if (sw & WAITFD_R) { 
-        FD_ZERO(&rfds); 
+    if (sw & WAITFD_R) {
+        FD_ZERO(&rfds);
         FD_SET(*ps, &rfds);
-        rp = &rfds; 
+        rp = &rfds;
     }
     if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
     if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; }
@@ -72,9 +73,9 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
 /*-------------------------------------------------------------------------*\
 * Select with int timeout in ms
 \*-------------------------------------------------------------------------*/
-int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, 
+int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
         p_timeout tm) {
-    struct timeval tv; 
+    struct timeval tv;
     double t = timeout_get(tm);
     tv.tv_sec = (int) t;
     tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
@@ -96,7 +97,7 @@ void socket_destroy(p_socket ps) {
 }
 
 /*-------------------------------------------------------------------------*\
-* 
+*
 \*-------------------------------------------------------------------------*/
 void socket_shutdown(p_socket ps, int how) {
     socket_setblocking(ps);
@@ -134,10 +135,10 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
         /* give windows time to set the error (yes, disgusting) */
         Sleep(10);
         /* find out why we failed */
-        getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); 
+        getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
         /* we KNOW there was an error. if 'why' is 0, we will return
         * "unknown error", but it's not really our fault */
-        return err > 0? err: IO_UNKNOWN; 
+        return err > 0? err: IO_UNKNOWN;
     } else return err;
 
 }
@@ -154,7 +155,7 @@ int socket_bind(p_socket ps, SA *addr, socklen_t len) {
 }
 
 /*-------------------------------------------------------------------------*\
-* 
+*
 \*-------------------------------------------------------------------------*/
 int socket_listen(p_socket ps, int backlog) {
     int err = IO_DONE;
@@ -167,7 +168,7 @@ int socket_listen(p_socket ps, int backlog) {
 /*-------------------------------------------------------------------------*\
 * Accept with timeout
 \*-------------------------------------------------------------------------*/
-int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, 
+int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len,
         p_timeout tm) {
     if (*ps == SOCKET_INVALID) return IO_CLOSED;
     for ( ;; ) {
@@ -175,21 +176,21 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len,
         /* try to get client socket */
         if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
         /* find out why we failed */
-        err = WSAGetLastError(); 
+        err = WSAGetLastError();
         /* if we failed because there was no connectoin, keep trying */
         if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err;
         /* call select to avoid busy wait */
         if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
-    } 
+    }
 }
 
 /*-------------------------------------------------------------------------*\
 * Send with timeout
-* On windows, if you try to send 10MB, the OS will buffer EVERYTHING 
-* this can take an awful lot of time and we will end up blocked. 
+* On windows, if you try to send 10MB, the OS will buffer EVERYTHING
+* this can take an awful lot of time and we will end up blocked.
 * Therefore, whoever calls this function should not pass a huge buffer.
 \*-------------------------------------------------------------------------*/
-int socket_send(p_socket ps, const char *data, size_t count, 
+int socket_send(p_socket ps, const char *data, size_t count,
         size_t *sent, p_timeout tm)
 {
     int err;
@@ -206,18 +207,18 @@ int socket_send(p_socket ps, const char *data, size_t count,
             return IO_DONE;
         }
         /* deal with failure */
-        err = WSAGetLastError(); 
+        err = WSAGetLastError();
         /* we can only proceed if there was no serious error */
         if (err != WSAEWOULDBLOCK) return err;
         /* avoid busy wait */
         if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
-    } 
+    }
 }
 
 /*-------------------------------------------------------------------------*\
 * Sendto with timeout
 \*-------------------------------------------------------------------------*/
-int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, 
+int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
         SA *addr, socklen_t len, p_timeout tm)
 {
     int err;
@@ -229,17 +230,17 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
             *sent = put;
             return IO_DONE;
         }
-        err = WSAGetLastError(); 
+        err = WSAGetLastError();
         if (err != WSAEWOULDBLOCK) return err;
         if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
-    } 
+    }
 }
 
 /*-------------------------------------------------------------------------*\
 * Receive with timeout
 \*-------------------------------------------------------------------------*/
-int socket_recv(p_socket ps, char *data, size_t count, size_t *got, 
-        p_timeout tm) 
+int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
+        p_timeout tm)
 {
     int err, prev = IO_DONE;
     *got = 0;
@@ -252,9 +253,9 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
         }
         if (taken == 0) return IO_CLOSED;
         err = WSAGetLastError();
-        /* On UDP, a connreset simply means the previous send failed. 
-         * So we try again. 
-         * On TCP, it means our socket is now useless, so the error passes. 
+        /* On UDP, a connreset simply means the previous send failed.
+         * So we try again.
+         * On TCP, it means our socket is now useless, so the error passes.
          * (We will loop again, exiting because the same error will happen) */
         if (err != WSAEWOULDBLOCK) {
             if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
@@ -267,8 +268,8 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
 /*-------------------------------------------------------------------------*\
 * Recvfrom with timeout
 \*-------------------------------------------------------------------------*/
-int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, 
-        SA *addr, socklen_t *len, p_timeout tm) 
+int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
+        SA *addr, socklen_t *len, p_timeout tm)
 {
     int err, prev = IO_DONE;
     *got = 0;
@@ -281,8 +282,8 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
         }
         if (taken == 0) return IO_CLOSED;
         err = WSAGetLastError();
-        /* On UDP, a connreset simply means the previous send failed. 
-         * So we try again. 
+        /* On UDP, a connreset simply means the previous send failed.
+         * So we try again.
          * On TCP, it means our socket is now useless, so the error passes.
          * (We will loop again, exiting because the same error will happen) */
         if (err != WSAEWOULDBLOCK) {
@@ -310,7 +311,7 @@ void socket_setnonblocking(p_socket ps) {
 }
 
 /*-------------------------------------------------------------------------*\
-* DNS helpers 
+* DNS helpers
 \*-------------------------------------------------------------------------*/
 int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
     *hp = gethostbyaddr(addr, len, AF_INET);
@@ -330,21 +331,21 @@ int socket_gethostbyname(const char *addr, struct hostent **hp) {
 const char *socket_hoststrerror(int err) {
     if (err <= 0) return io_strerror(err);
     switch (err) {
-        case WSAHOST_NOT_FOUND: return "host not found";
-        default: return wstrerror(err); 
+        case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND;
+        default: return wstrerror(err);
     }
 }
 
 const char *socket_strerror(int err) {
     if (err <= 0) return io_strerror(err);
     switch (err) {
-        case WSAEADDRINUSE: return "address already in use";
-        case WSAECONNREFUSED: return "connection refused";
-        case WSAEISCONN: return "already connected";
-        case WSAEACCES: return "permission denied";
-        case WSAECONNABORTED: return "closed";
-        case WSAECONNRESET: return "closed";
-        case WSAETIMEDOUT: return "timeout";
+        case WSAEADDRINUSE: return PIE_ADDRINUSE;
+        case WSAECONNREFUSED : return PIE_CONNREFUSED;
+        case WSAEISCONN: return PIE_ISCONN;
+        case WSAEACCES: return PIE_ACCESS;
+        case WSAECONNABORTED: return PIE_CONNABORTED;
+        case WSAECONNRESET: return PIE_CONNRESET;
+        case WSAETIMEDOUT: return PIE_TIMEDOUT;
         default: return wstrerror(err);
     }
 }
@@ -357,7 +358,7 @@ const char *socket_ioerror(p_socket ps, int err) {
 static const char *wstrerror(int err) {
     switch (err) {
         case WSAEINTR: return "Interrupted function call";
-        case WSAEACCES: return "Permission denied";
+        case WSAEACCES: return PIE_ACCESS; // "Permission denied";
         case WSAEFAULT: return "Bad address";
         case WSAEINVAL: return "Invalid argument";
         case WSAEMFILE: return "Too many open files";
@@ -370,63 +371,61 @@ static const char *wstrerror(int err) {
         case WSAEPROTOTYPE: return "Protocol wrong type for socket";
         case WSAENOPROTOOPT: return "Bad protocol option";
         case WSAEPROTONOSUPPORT: return "Protocol not supported";
-        case WSAESOCKTNOSUPPORT: return "Socket type not supported";
+        case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported";
         case WSAEOPNOTSUPP: return "Operation not supported";
         case WSAEPFNOSUPPORT: return "Protocol family not supported";
-        case WSAEAFNOSUPPORT: 
-            return "Address family not supported by protocol family"; 
-        case WSAEADDRINUSE: return "Address already in use";
+        case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family";
+        case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use";
         case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
         case WSAENETDOWN: return "Network is down";
         case WSAENETUNREACH: return "Network is unreachable";
         case WSAENETRESET: return "Network dropped connection on reset";
         case WSAECONNABORTED: return "Software caused connection abort";
-        case WSAECONNRESET: return "Connection reset by peer";
+        case WSAECONNRESET: return PIE_CONNRESET; // "Connection reset by peer";
         case WSAENOBUFS: return "No buffer space available";
-        case WSAEISCONN: return "Socket is already connected";
+        case WSAEISCONN: return PIE_ISCONN; // "Socket is already connected";
         case WSAENOTCONN: return "Socket is not connected";
         case WSAESHUTDOWN: return "Cannot send after socket shutdown";
-        case WSAETIMEDOUT: return "Connection timed out";
-        case WSAECONNREFUSED: return "Connection refused";
+        case WSAETIMEDOUT: return PIE_TIMEDOUT; // "Connection timed out";
+        case WSAECONNREFUSED: return PIE_CONNREFUSED; // "Connection refused";
         case WSAEHOSTDOWN: return "Host is down";
         case WSAEHOSTUNREACH: return "No route to host";
         case WSAEPROCLIM: return "Too many processes";
         case WSASYSNOTREADY: return "Network subsystem is unavailable";
         case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range";
-        case WSANOTINITIALISED: 
+        case WSANOTINITIALISED:
             return "Successful WSAStartup not yet performed";
         case WSAEDISCON: return "Graceful shutdown in progress";
-        case WSAHOST_NOT_FOUND: return "Host not found";
+        case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found";
         case WSATRY_AGAIN: return "Nonauthoritative host not found";
-        case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; 
+        case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error";
         case WSANO_DATA: return "Valid name, no data record of requested type";
         default: return "Unknown error";
     }
 }
 
 const char *socket_gaistrerror(int err) {
-    if (err == 0) return NULL; 
+    if (err == 0) return NULL;
     switch (err) {
-        case EAI_AGAIN: return "temporary failure in name resolution";
-        case EAI_BADFLAGS: return "invalid value for ai_flags";
+        case EAI_AGAIN: return PIE_AGAIN;
+        case EAI_BADFLAGS: return PIE_BADFLAGS;
 #ifdef EAI_BADHINTS
-        case EAI_BADHINTS: return "invalid value for hints";
+        case EAI_BADHINTS: return PIE_BADHINTS;
 #endif
-        case EAI_FAIL: return "non-recoverable failure in name resolution";
-        case EAI_FAMILY: return "ai_family not supported";
-        case EAI_MEMORY: return "memory allocation failure";
-        case EAI_NONAME: 
-            return "host or service not provided, or not known";
+        case EAI_FAIL: return PIE_FAIL;
+        case EAI_FAMILY: return PIE_FAMILY;
+        case EAI_MEMORY: return PIE_MEMORY;
+        case EAI_NONAME: return PIE_NONAME;
 #ifdef EAI_OVERFLOW
-        case EAI_OVERFLOW: return "argument buffer overflow";
+        case EAI_OVERFLOW: return PIE_OVERFLOW;
 #endif
 #ifdef EAI_PROTOCOL
-        case EAI_PROTOCOL: return "resolved protocol is unknown";
+        case EAI_PROTOCOL: return PIE_PROTOCOL;
 #endif
-        case EAI_SERVICE: return "service not supported for socket type";
-        case EAI_SOCKTYPE: return "ai_socktype not supported";
+        case EAI_SERVICE: return PIE_SERVICE;
+        case EAI_SOCKTYPE: return PIE_SOCKTYPE;
 #ifdef EAI_SYSTEM
-        case EAI_SYSTEM: return strerror(errno); 
+        case EAI_SYSTEM: return strerror(errno);
 #endif
         default: return gai_strerror(err);
     }
diff --git a/test/auth/.htaccess b/test/auth/.htaccess
new file mode 100644
index 0000000..bb2794a
--- /dev/null
+++ b/test/auth/.htaccess
@@ -0,0 +1,4 @@
+AuthName "test-auth"
+    AuthType Basic
+    AuthUserFile /Users/diego/impa/luasocket/test/auth/.htpasswd
+    Require valid-user
diff --git a/test/auth/.htpasswd b/test/auth/.htpasswd
index fd9002b..cfb2603 100644
--- a/test/auth/.htpasswd
+++ b/test/auth/.htpasswd
@@ -1 +1 @@
-luasocket:l8n2npozPB.sQ
+luasocket:$apr1$47u2O.Me$.m/5BWAtt7GVoxsouIPBR1
diff --git a/test/excepttest.lua b/test/excepttest.lua
index ce9f197..80c9cb8 100644
--- a/test/excepttest.lua
+++ b/test/excepttest.lua
@@ -1,6 +1,30 @@
 local socket = require("socket")
-try = socket.newtry(function()
-    print("finalized!!!")
+
+local finalizer_called
+
+local func = socket.protect(function(err, ...)
+    local try = socket.newtry(function()
+        finalizer_called = true
+    end)
+
+    if err then
+        return error(err, 0)
+    else
+        return try(...)
+    end
 end)
-try = socket.protect(try)
-print(try(nil, "it works"))
+
+local ret1, ret2, ret3 = func(false, 1, 2, 3)
+assert(not finalizer_called, "unexpected finalizer call")
+assert(ret1 == 1 and ret2 == 2 and ret3 == 3, "incorrect return values")
+
+ret1, ret2, ret3 = func(false, false, "error message")
+assert(finalizer_called, "finalizer not called")
+assert(ret1 == nil and ret2 == "error message" and ret3 == nil, "incorrect return values")
+
+local err = {key = "value"}
+ret1, ret2 = pcall(func, err)
+assert(not ret1, "error not rethrown")
+assert(ret2 == err, "incorrect error rethrown")
+
+print("OK")
diff --git a/test/httptest.lua b/test/httptest.lua
index d5fbb37..63ff921 100644
--- a/test/httptest.lua
+++ b/test/httptest.lua
@@ -1,4 +1,4 @@
--- needs Alias from /home/c/diego/tec/luasocket/test to 
+-- needs Alias from /home/c/diego/tec/luasocket/test to
 -- "/luasocket-test" and "/luasocket-test/"
 -- needs ScriptAlias from /home/c/diego/tec/luasocket/test/cgi
 -- to "/luasocket-test-cgi" and "/luasocket-test-cgi/"
@@ -36,22 +36,22 @@ index = readfile(index_file)
 local check_result = function(response, expect, ignore)
     for i,v in pairs(response) do
         if not ignore[i] then
-            if v ~= expect[i] then 
+            if v ~= expect[i] then
                 local f = io.open("err", "w")
                 f:write(tostring(v), "\n\n versus\n\n", tostring(expect[i]))
                 f:close()
-                fail(i .. " differs!") 
+                fail(i .. " differs!")
             end
         end
     end
     for i,v in pairs(expect) do
         if not ignore[i] then
-            if v ~= response[i] then 
+            if v ~= response[i] then
                 local f = io.open("err", "w")
                 f:write(tostring(response[i]), "\n\n versus\n\n", tostring(v))
                 v = string.sub(type(v) == "string" and v or "", 1, 70)
                 f:close()
-                fail(i .. " differs!") 
+                fail(i .. " differs!")
             end
         end
     end
@@ -61,10 +61,10 @@ end
 local check_request = function(request, expect, ignore)
     local t
     if not request.sink then request.sink, t = ltn12.sink.table() end
-    request.source = request.source or 
+    request.source = request.source or
         (request.body and ltn12.source.string(request.body))
     local response = {}
-    response.code, response.headers, response.status = 
+    response.code, response.headers, response.status =
         socket.skip(1, http.request(request))
     if t and #t > 0 then response.body = table.concat(t) end
     check_result(response, expect, ignore)
@@ -82,7 +82,7 @@ else fail(back.query) end
 ------------------------------------------------------------------------
 io.write("testing query string correctness: ")
 forth = "this+is+the+query+string"
-back = http.request("http://" .. host .. cgiprefix .. 
+back = http.request("http://" .. host .. cgiprefix ..
     "/query-string?" .. forth)
 if similar(back, forth) then print("ok")
 else fail("failed!") end
@@ -120,10 +120,10 @@ check_request(request, expect, ignore)
 ------------------------------------------------------------------------
 io.write("testing invalid url: ")
 local r, e = http.request{url = host .. prefix}
-assert(r == nil and e == "invalid host ''") 
+assert(r == nil and e == "invalid host ''")
 r, re = http.request(host .. prefix)
-assert(r == nil and e == re, tostring(r) ..", " .. tostring(re) .. 
-    " vs " .. tostring(e)) 
+assert(r == nil and e == re, tostring(r) ..", " .. tostring(re) ..
+    " vs " .. tostring(e))
 print("ok")
 
 io.write("testing invalid empty port: ")
@@ -212,7 +212,7 @@ os.remove(index_file .. "-back")
 io.write("testing ltn12.(sink|source).chain and mime.(encode|decode): ")
 
 local function b64length(len)
-    local a = math.ceil(len/3)*4 
+    local a = math.ceil(len/3)*4
     local l = math.ceil(a/76)
     return a + l*2
 end
@@ -313,7 +313,7 @@ ignore = {
     headers = 1
 }
 check_request(request, expect, ignore)
-    
+
 ------------------------------------------------------------------------
 io.write("testing document not found: ")
 request = {
@@ -429,9 +429,9 @@ print("ok")
 io.write("testing host not found: ")
 local c, e = socket.connect("example.invalid", 80)
 local r, re = http.request{url = "http://example.invalid/does/not/exist"}
-assert(r == nil and e == re, tostring(r) .. " " .. tostring(re)) 
+assert(r == nil and e == re, tostring(r) .. " " .. tostring(re))
 r, re = http.request("http://example.invalid/does/not/exist")
-assert(r == nil and e == re) 
+assert(r == nil and e == re)
 print("ok")
 
 ------------------------------------------------------------------------
diff --git a/test/ltn12test.lua b/test/ltn12test.lua
index 74a45e8..e3f85fb 100644
--- a/test/ltn12test.lua
+++ b/test/ltn12test.lua
@@ -192,6 +192,21 @@ assert(filter(nil, 1), "filter not empty")
 print("ok")
 
 --------------------------------
+io.write("testing source.chain (with several filters): ")
+local function double(x) -- filter turning "ABC" into "AABBCC"
+    if not x then return end
+    local b={}
+    for k in x:gmatch'.' do table.insert(b, k..k) end
+    return table.concat(b)
+end
+source = ltn12.source.string(s)
+source = ltn12.source.chain(source, double, double, double)
+sink, t = ltn12.sink.table()
+assert(ltn12.pump.all(source, sink), "returned error")
+assert(table.concat(t) == double(double(double(s))), "mismatch")
+print("ok")
+
+--------------------------------
 io.write("testing source.chain (with split) and sink.chain (with merge): ")
 source = ltn12.source.string(s)
 filter = split(5)
@@ -206,6 +221,15 @@ assert(filter2(nil, 1), "filter2 not empty")
 print("ok")
 
 --------------------------------
+io.write("testing sink.chain (with several filters): ")
+source = ltn12.source.string(s)
+sink, t = ltn12.sink.table()
+sink = ltn12.sink.chain(double, double, double, sink)
+assert(ltn12.pump.all(source, sink), "returned error")
+assert(table.concat(t) == double(double(double(s))), "mismatch")
+print("ok")
+
+--------------------------------
 io.write("testing filter.chain (and sink.chain, with split, merge): ")
 source = ltn12.source.string(s)
 filter = split(5)
@@ -272,3 +296,4 @@ assert(filter3(nil, 1), "filter3 not empty")
 assert(filter4(nil, 1), "filter4 not empty")
 assert(filter5(nil, 1), "filter5 not empty")
 print("ok")
+
diff --git a/test/testclnt.lua b/test/testclnt.lua
index 315783b..170e187 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -8,7 +8,7 @@ function printf(...)
 end
 
 function pass(...)
-    printf(...) 
+    printf(...)
     io.stderr:write("\n")
 end
 
@@ -45,30 +45,30 @@ function check_timeout(tm, sl, elapsed, err, opp, mode, alldone)
             if not err then warn("must be buffered")
             elseif err == "timeout" then pass("proper timeout")
             else fail("unexpected error '%s'", err) end
-        else 
-            if err ~= "timeout" then fail("should have timed out") 
+        else
+            if err ~= "timeout" then fail("should have timed out")
             else pass("proper timeout") end
         end
     else
         if mode == "total" then
-            if elapsed > tm then 
+            if elapsed > tm then
                 if err ~= "timeout" then fail("should have timed out")
                 else pass("proper timeout") end
             elseif elapsed < tm then
-                if err then fail(err) 
+                if err then fail(err)
                 else pass("ok") end
-            else 
-                if alldone then 
-                    if err then fail("unexpected error '%s'", err) 
+            else
+                if alldone then
+                    if err then fail("unexpected error '%s'", err)
                     else pass("ok") end
                 else
-                    if err ~= "timeout" then fail(err) 
+                    if err ~= "timeout" then fail(err)
                     else pass("proper timeoutk") end
                 end
             end
-        else 
-            if err then fail(err) 
-            else pass("ok") end 
+        else
+            if err then fail(err)
+            else pass("ok") end
         end
     end
 end
@@ -104,8 +104,8 @@ control:setoption("tcp-nodelay", true)
 ------------------------------------------------------------------------
 function test_methods(sock, methods)
     for _, v in pairs(methods) do
-        if type(sock[v]) ~= "function" then 
-            fail(sock.class .. " method '" .. v .. "' not registered") 
+        if type(sock[v]) ~= "function" then
+            fail(sock.class .. " method '" .. v .. "' not registered")
         end
     end
     pass(sock.class .. " methods are ok")
@@ -121,7 +121,7 @@ function test_mixed(len)
     local p3 = "raw " .. string.rep("z", inter) .. "bytes"
     local p4 = "end" .. string.rep("w", inter) .. "bytes"
     local bp1, bp2, bp3, bp4
-remote (string.format("str = data:receive(%d)", 
+remote (string.format("str = data:receive(%d)",
             string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4)))
     sent, err = data:send(p1..p2..p3..p4)
     if err then fail(err) end
@@ -166,7 +166,7 @@ function test_rawline(len)
     io.stderr:write("length " .. len .. ": ")
     local str, str10, back, err
     str = string.rep(string.char(47), math.mod(len, 10))
-    str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100), 
+    str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
             math.floor(len/10))
     str = str .. str10
 remote "str = data:receive()"
@@ -216,7 +216,7 @@ function test_totaltimeoutreceive(len, tm, sl)
     data:settimeout(tm, "total")
 local t = socket.gettime()
     str, err, partial, elapsed = data:receive(2*len)
-    check_timeout(tm, sl, elapsed, err, "receive", "total", 
+    check_timeout(tm, sl, elapsed, err, "receive", "total",
         string.len(str or partial) == 2*len)
 end
 
@@ -236,7 +236,7 @@ function test_totaltimeoutsend(len, tm, sl)
     data:settimeout(tm, "total")
     str = string.rep("a", 2*len)
     total, err, partial, elapsed = data:send(str)
-    check_timeout(tm, sl, elapsed, err, "send", "total", 
+    check_timeout(tm, sl, elapsed, err, "send", "total",
         total == 2*len)
 end
 
@@ -256,7 +256,7 @@ function test_blockingtimeoutreceive(len, tm, sl)
     ]], 2*tm, len, sl, sl))
     data:settimeout(tm)
     str, err, partial, elapsed = data:receive(2*len)
-    check_timeout(tm, sl, elapsed, err, "receive", "blocking", 
+    check_timeout(tm, sl, elapsed, err, "receive", "blocking",
         string.len(str or partial) == 2*len)
 end
 
@@ -290,10 +290,10 @@ function empty_connect()
         data = server:accept()
     ]]
     data, err = socket.connect("", port)
-    if not data then 
+    if not data then
         pass("ok")
         data = socket.connect(host, port)
-    else 
+    else
         pass("gethostbyname returns localhost on empty string...")
     end
 end
@@ -304,15 +304,20 @@ function isclosed(c)
 end
 
 function active_close()
-    reconnect()
-    if isclosed(data) then fail("should not be closed") end
-    data:close()
-    if not isclosed(data) then fail("should be closed") end
-    data = nil
-    local udp = socket.udp()
+    local tcp = socket.tcp4()
+    if isclosed(tcp) then fail("should not be closed") end
+    tcp:close()
+    if not isclosed(tcp) then fail("should be closed") end
+    tcp = socket.tcp()
+    if not isclosed(tcp) then fail("should be closed") end
+    tcp = nil
+    local udp = socket.udp4()
     if isclosed(udp) then fail("should not be closed") end
     udp:close()
     if not isclosed(udp) then fail("should be closed") end
+    udp = socket.udp()
+    if not isclosed(udp) then fail("should be closed") end
+    udp = nil
     pass("ok")
 end
 
@@ -327,7 +332,7 @@ function test_closed()
         data:close()
         data = nil
     ]], str))
-    -- try to get a line 
+    -- try to get a line
     back, err, partial = data:receive()
     if not err then fail("should have gotten 'closed'.")
     elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.")
@@ -340,25 +345,25 @@ function test_closed()
         data = nil
     ]]
     total, err, partial = data:send(string.rep("ugauga", 100000))
-    if not err then 
+    if not err then
         pass("failed: output buffer is at least %d bytes long!", total)
-    elseif err ~= "closed" then 
+    elseif err ~= "closed" then
         fail("got '"..err.."' instead of 'closed'.")
-    else 
-        pass("graceful 'closed' received after %d bytes were sent", partial) 
+    else
+        pass("graceful 'closed' received after %d bytes were sent", partial)
     end
 end
 
 ------------------------------------------------------------------------
 function test_selectbugs()
     local r, s, e = socket.select(nil, nil, 0.1)
-    assert(type(r) == "table" and type(s) == "table" and 
+    assert(type(r) == "table" and type(s) == "table" and
         (e == "timeout" or e == "error"))
     pass("both nil: ok")
     local udp = socket.udp()
     udp:close()
     r, s, e = socket.select({ udp }, { udp }, 0.1)
-    assert(type(r) == "table" and type(s) == "table" and 
+    assert(type(r) == "table" and type(s) == "table" and
         (e == "timeout" or e == "error"))
     pass("closed sockets: ok")
     e = pcall(socket.select, "wrong", 1, 0.1)
@@ -368,7 +373,7 @@ function test_selectbugs()
     pass("invalid input: ok")
     local toomany = {}
     for i = 1, socket._SETSIZE+1 do
-        toomany[#toomany+1] = socket.udp()
+        toomany[#toomany+1] = socket.udp4()
     end
     if #toomany > socket._SETSIZE then
         local e = pcall(socket.select, toomany, nil, 0.1)
@@ -389,7 +394,7 @@ function accept_timeout()
     local t = socket.gettime()
     s:settimeout(1)
     local c, e = s:accept()
-    assert(not c, "should not accept") 
+    assert(not c, "should not accept")
     assert(e == "timeout", string.format("wrong error message (%s)", e))
     t = socket.gettime() - t
     assert(t < 2, string.format("took to long to give up (%gs)", t))
@@ -407,9 +412,9 @@ function connect_timeout()
     local t = socket.gettime()
     local r, e = c:connect("10.0.0.1", 81)
     assert(not r, "should not connect")
-    assert(socket.gettime() - t < 2, "took too long to give up.") 
+    assert(socket.gettime() - t < 2, "took too long to give up.")
     c:close()
-    pass("ok") 
+    pass("ok")
 end
 
 ------------------------------------------------------------------------
@@ -447,16 +452,14 @@ end
 
 ------------------------------------------------------------------------
 function rebind_test()
-    --local c ,c1 = socket.bind("localhost", 0)
    local c ,c1 = socket.bind("127.0.0.1", 0)
     if not c then pass ("failed to bind! " .. tostring(c) .. ' ' .. tostring(c1))  return end
 	assert(c,c1)
- 
     local i, p = c:getsockname()
     local s, e = socket.tcp()
     assert(s, e)
     s:setoption("reuseaddr", false)
-    r, e = s:bind("localhost", p)
+    r, e = s:bind(i, p)
     assert(not r, "managed to rebind!")
     assert(e)
     pass("ok")
@@ -476,9 +479,9 @@ function getstats_test()
         data:receive(c)
         t = t + c
         local r, s, a = data:getstats()
-        assert(r == t, "received count failed" .. tostring(r) 
+        assert(r == t, "received count failed" .. tostring(r)
             .. "/" .. tostring(t))
-        assert(s == t, "sent count failed" .. tostring(s) 
+        assert(s == t, "sent count failed" .. tostring(s)
             .. "/" .. tostring(t))
     end
     pass("ok")
@@ -486,7 +489,7 @@ end
 
 
 ------------------------------------------------------------------------
-function test_nonblocking(size) 
+function test_nonblocking(size)
     reconnect()
     printf("testing "  .. 2*size .. " bytes: ")
 remote(string.format([[
@@ -545,7 +548,7 @@ function test_readafterclose()
         data:close()
         data = nil
     ]]))
-    data:close() 
+    data:close()
     back, err, partial = data:receive("*a")
     assert(back == nil and err == "closed", "should have returned 'closed'")
     pass("ok")
@@ -555,7 +558,7 @@ function test_readafterclose()
         data:close()
         data = nil
     ]]))
-    data:close() 
+    data:close()
     back, err, partial = data:receive()
     assert(back == nil and err == "closed", "should have returned 'closed'")
     pass("ok")
@@ -565,7 +568,7 @@ function test_readafterclose()
         data:close()
         data = nil
     ]]))
-    data:close() 
+    data:close()
     back, err, partial = data:receive(1)
     assert(back == nil and err == "closed", "should have returned 'closed'")
     pass("ok")
@@ -575,7 +578,7 @@ function test_readafterclose()
         data:close()
         data = nil
     ]]))
-    data:close() 
+    data:close()
     back, err, partial = data:receive(0)
     assert(back == nil and err == "closed", "should have returned 'closed'")
     pass("ok")
@@ -590,10 +593,10 @@ function test_writeafterclose()
         data = nil
     ]]))
     local sent, err, errsent
-    while not err do 
+    while not err do
         sent, err, errsent, time = data:send(str)
     end
-    assert(err == "closed", "should have returned 'closed'")
+    assert(err == "closed", "got " .. err .. " instead of 'closed'")
     pass("ok")
 end
 
@@ -648,25 +651,24 @@ else io.stderr:write("Warning! IPv6 does not support!\n") end
 end
 
 local udp_methods = {
-    "close", 
+    "close",
     "dirty",
     "getfamily",
     "getfd",
     "getoption",
     "getpeername",
     "getsockname",
-    "receive", 
-    "receivefrom", 
-    "send", 
-    "sendto", 
-    "setfd", 
+    "receive",
+    "receivefrom",
+    "send",
+    "sendto",
+    "setfd",
     "setoption",
     "setpeername",
     "setsockname",
     "settimeout"
 }
 
-
 ------------------------------------------------------------------------
 test_methods(socket.udp(), udp_methods)
 do local sock = socket.tcp6()
@@ -674,6 +676,9 @@ if sock then test_methods(socket.udp6(), udp_methods)
 else io.stderr:write("Warning! IPv6 does not support!\n") end
 end
 
+test("closed connection detection: ")
+test_closed()
+
 test("partial receive")
 test_partialrecv()
 
@@ -697,9 +702,6 @@ rebind_test()
 test("active close: ")
 active_close()
 
-test("closed connection detection: ")
-test_closed()
-
 test("accept function: ")
 accept_timeout()
 accept_errors()
diff --git a/test/testsrvr.lua b/test/testsrvr.lua
index 72b93ab..1eb2d5b 100644
--- a/test/testsrvr.lua
+++ b/test/testsrvr.lua
@@ -6,7 +6,7 @@ ack = "\n";
 while 1 do
     print("server: waiting for client connection...");
     control = assert(server:accept());
-    while 1 do 
+    while 1 do
         command, emsg = control:receive();
         if emsg == "closed" then
             control:close()
diff --git a/test/udpconnectclnt.lua b/test/udpconnectclnt.lua
index effe13a..ad6ab6a 100644
--- a/test/udpconnectclnt.lua
+++ b/test/udpconnectclnt.lua
@@ -1,7 +1,7 @@
 local socket = require"socket"
 local udp = socket.udp
 local localhost = "127.0.0.1"
-local port = arg[1]
+local port = assert(arg[1], "missing port argument")
 
 se = udp(); se:setoption("reuseaddr", true)
 se:setsockname(localhost, 5062)
diff --git a/win32.cmd b/win32.cmd
index 48522f0..3045721 100644
--- a/win32.cmd
+++ b/win32.cmd
@@ -1,12 +1 @@
-make PLAT=win32 LUAV=5.2 LUAINC_win32='c:\cygwin\home\diego\build\include' LUALIB_win32='c:\cygwin\home\diego\build\bin\release'
-
-#!/bin/sh
-for p in Release Debug x64/Release x64/Debug; do
-    for el in mime socket; do
-        for e in dll lib; do
-            cp $p/$el/core.$e ../bin/$p/$el/
-        done;
-    done;
-    cp src/ltn12.lua src/socket.lua src/mime.lua ../bin/$p/
-    cp src/http.lua src/url.lua src/tp.lua src/ftp.lua src/headers.lua src/smtp.lua ../bin/$p/socket/
-done;
+make LUAPREFIX_win32='c:\cygwin\home\diego\vc12' LUAV=5.1 PLAT=win32 LUALIBNAME_win32=lualib.lib PLATFORM_win32=Debug install-both