1#include <Python.h>
2#include "pyobjc-api.h"
3#include <sys/socket.h>
4#include <netinet/in.h>
5#include <arpa/inet.h>
6#include <netdb.h>
7
8#import <Foundation/Foundation.h>
9
10@interface PyObjCTestSockAddr : NSObject
11{
12}
13+(NSObject*)sockAddrToValue:(struct sockaddr*)addr;
14+(void) getIPv4Addr:(struct sockaddr*)buf;
15+(void) getIPv6Addr:(struct sockaddr*)buf;
16@end
17
18static NSString*
19addr2string(void* addr, int addrlen)
20{
21	char buf[NI_MAXHOST];
22	int error;
23
24	error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
25			NI_NUMERICHOST);
26	if (error) {
27		return NULL;
28	}
29	return [NSString stringWithUTF8String:buf];
30}
31
32
33@implementation PyObjCTestSockAddr
34+(NSObject*)sockAddrToValue:(struct sockaddr*)addr
35{
36	NSMutableArray* array = [NSMutableArray array];
37		
38	switch (addr->sa_family) {
39	case AF_INET:
40		[array addObject:@"IPv4"];
41		[array addObject: addr2string(addr, sizeof(struct sockaddr_in))];
42		[array addObject:[NSNumber numberWithShort:ntohs(((struct sockaddr_in*)addr)->sin_port)]];
43		return array;
44		break;
45	case AF_INET6:
46		[array addObject:@"IPv6"];
47		[array addObject: addr2string(addr, sizeof(struct sockaddr_in6))];
48		[array addObject: [NSNumber numberWithShort:ntohs(((struct sockaddr_in6*)addr)->sin6_port)]];
49		[array addObject: [NSNumber numberWithUnsignedLong:(((struct sockaddr_in6*)addr)->sin6_flowinfo)]];
50		[array addObject: [NSNumber numberWithUnsignedLong:(((struct sockaddr_in6*)addr)->sin6_scope_id)]];		
51		return array;
52		break;
53	default:
54		return NULL;
55	}
56}
57
58+(void) getIPv4Addr:(struct sockaddr*)buf
59{
60	struct sockaddr_in* addr = (struct sockaddr_in*)buf;
61	addr->sin_family = AF_INET;
62	addr->sin_port = htons(80);
63	ascii2addr(AF_INET, "127.0.0.1", &addr->sin_addr);
64}
65
66+(void) getIPv6Addr:(struct sockaddr*)buf
67{
68	struct sockaddr_in6* addr = (struct sockaddr_in6*)buf;
69	addr->sin6_family = AF_INET6;
70	addr->sin6_port = htons(443);
71	addr->sin6_flowinfo = 2;
72	addr->sin6_scope_id = 3;
73	((char*)&addr->sin6_addr)[0] = 0;
74	((char*)&addr->sin6_addr)[1] = 0;
75	((char*)&addr->sin6_addr)[2] = 0;
76	((char*)&addr->sin6_addr)[3] = 0;
77	((char*)&addr->sin6_addr)[4] = 0;
78	((char*)&addr->sin6_addr)[5] = 0;
79	((char*)&addr->sin6_addr)[6] = 0;
80	((char*)&addr->sin6_addr)[7] = 0;
81	((char*)&addr->sin6_addr)[8] = 0;
82	((char*)&addr->sin6_addr)[9] = 0;
83	((char*)&addr->sin6_addr)[10] = 0;
84	((char*)&addr->sin6_addr)[11] = 0;
85	((char*)&addr->sin6_addr)[12] = 0;
86	((char*)&addr->sin6_addr)[13] = 0;
87	((char*)&addr->sin6_addr)[14] = 0;
88	((char*)&addr->sin6_addr)[15] = 1;
89}
90@end
91
92static PyMethodDef mod_methods[] = {
93	{ 0, 0, 0, 0}
94};
95
96#if PY_VERSION_HEX >= 0x03000000
97
98static struct PyModuleDef mod_module = {
99	PyModuleDef_HEAD_INIT,
100	"sockaddr",
101	NULL,
102	0,
103	mod_methods,
104	NULL,
105	NULL,
106	NULL,
107	NULL
108};
109
110#define INITERROR() return NULL
111#define INITDONE() return m
112
113PyObject* PyInit_sockaddr(void);
114
115PyObject*
116PyInit_sockaddr(void)
117
118#else
119
120#define INITERROR() return
121#define INITDONE() return
122
123void initsockaddr(void);
124
125void
126initsockaddr(void)
127#endif
128{
129	PyObject* m;
130
131#if PY_VERSION_HEX >= 0x03000000
132	m = PyModule_Create(&mod_module);
133#else
134	m = Py_InitModule4("sockaddr", mod_methods,
135		NULL, NULL, PYTHON_API_VERSION);
136#endif
137	if (!m) {
138		INITERROR();
139	}
140
141	if (PyObjC_ImportAPI(m) < 0) {
142		INITERROR();
143	}
144
145	if (PyModule_AddObject(m, "PyObjCTestSockAddr",
146		PyObjCClass_New([PyObjCTestSockAddr class])) < 0) {
147		INITERROR();
148	}
149
150	INITDONE();
151
152}
153