blob: f3634787a19b795cadc14a6bcd58d0aa5f172947 [file] [log] [blame]
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +04001/*GPRSSocket.cpp
2 *
3 * Copyright (C) 2011 Ivan Klyuchnikov
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <Sockets.h>
21#include <Threads.h>
22#include <BitVector.h>
23#include "GPRSSocket.h"
24#include "gsm_rlcmac.h"
25#include "bssgp.h"
26
27#define MAX_UDP_LENGTH 1500
28
29#define RLCMAC_DATA_BLOCK 0
30#define RLCMAC_CONTROL_BLOCK 1
31
32// TODO: We should take ports and IP from config.
33UDPSocket GPRSRLCMACSocket(5070, "127.0.0.1", 5934);
34
35void sendToOpenBTS(BitVector * vector)
36{
37 char buffer[MAX_UDP_LENGTH];
38 int ofs = 0;
39 vector->pack((unsigned char*)&buffer[ofs]);
40 ofs += vector->size() >> 3;
41 COUT("Send to OpenBTS: " << *vector);
42 GPRSRLCMACSocket.write(buffer, ofs);
43}
44
45void writePDassignment(BitVector * dest, uint8_t TFI, uint32_t TLLI)
46{
47 // TODO We should use our implementation of encode RLC/MAC Control messages.
48 unsigned wp = 0;
49 dest->writeField(wp,0x1,2); // Payload Type
50 dest->writeField(wp,0x0,2); // Uplink block with TDMA framenumber
51 dest->writeField(wp,0x1,1); // Suppl/Polling Bit
52 dest->writeField(wp,0x1,3); // Uplink state flag
53 dest->writeField(wp,0x2,6); // MESSAGE TYPE
54 dest->writeField(wp,0x0,2); // Page Mode
55
56 dest->writeField(wp,0x0,1); // switch PERSIST_LEVEL: off
57 dest->writeField(wp,0x2,2); // switch TLLI : on
58 dest->writeField(wp,TLLI,32); // TLLI
59
60 dest->writeField(wp,0x0,1); // Message escape
61 dest->writeField(wp,0x0,2); // Medium Access Method: Dynamic Allocation
62 dest->writeField(wp,0x0,1); // RLC acknowledged mode
63
64 dest->writeField(wp,0x0,1); // the network establishes no new downlink TBF for the mobile station
65 dest->writeField(wp,0x1,8); // timeslot 7
66 dest->writeField(wp,0x1,8); // TIMING_ADVANCE_INDEX
67
68 dest->writeField(wp,0x0,1); // switch TIMING_ADVANCE_VALUE = off
69 dest->writeField(wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
70 dest->writeField(wp,0xC,4); // TIMING_ADVANCE_INDEX
71 dest->writeField(wp,0x7,3); // TIMING_ADVANCE_TIMESLOT_NUMBER
72
73 dest->writeField(wp,0x0,1); // switch POWER CONTROL = off
74 dest->writeField(wp,0x1,1); // Frequency Parameters information elements = present
75
76 dest->writeField(wp,0x2,3); // Training Sequence Code (TSC) = 2
77 dest->writeField(wp,0x1,2); // Indirect encoding struct = present
78 dest->writeField(wp,0x0,6); // MAIO
79 dest->writeField(wp,0xE,4); // MA_Number
80 dest->writeField(wp,0x8,4); // CHANGE_MARK_1 CHANGE_MARK_2
81
82 dest->writeField(wp,0x1,1); // switch TFI : on
83 dest->writeField(wp,0x14,5);// TFI
84
85 dest->writeField(wp,0x1,1); // Power Control Parameters IE = present
86 dest->writeField(wp,0x0,4); // ALPHA power control parameter
87 dest->writeField(wp,0x0,1); // switch GAMMA_TN0 = off
88 dest->writeField(wp,0x0,1); // switch GAMMA_TN1 = off
89 dest->writeField(wp,0x0,1); // switch GAMMA_TN2 = off
90 dest->writeField(wp,0x0,1); // switch GAMMA_TN3 = off
91 dest->writeField(wp,0x0,1); // switch GAMMA_TN4 = off
92 dest->writeField(wp,0x0,1); // switch GAMMA_TN5 = off
93 dest->writeField(wp,0x0,1); // switch GAMMA_TN6 = off
94 dest->writeField(wp,0x1,1); // switch GAMMA_TN7 = on
95 dest->writeField(wp,0x0,5); // GAMMA_TN7
96
97 dest->writeField(wp,0x0,1); // TBF Starting TIME IE not present
98 dest->writeField(wp,0x0,1); // Measurement Mapping struct not present
99}
100
101void writePUack(BitVector * dest, uint8_t TFI, uint32_t TLLI, unsigned CV, unsigned BSN)
102{
103 // TODO We should use our implementation of encode RLC/MAC Control messages.
104 unsigned wp = 0;
105 dest->writeField(wp,0x1,2); // payload
106 dest->writeField(wp,0x0,2); // Uplink block with TDMA framenumber
107 if (CV == 0) dest->writeField(wp,0x1,1); // Suppl/Polling Bit
108 else dest->writeField(wp,0x0,1); //Suppl/Polling Bit
109 dest->writeField(wp,0x1,3); // Uplink state flag
110
111 //dest->writeField(wp,0x0,1); // Reduced block sequence number
112 //dest->writeField(wp,BSN+6,5); // Radio transaction identifier
113 //dest->writeField(wp,0x1,1); // Final segment
114 //dest->writeField(wp,0x1,1); // Address control
115
116 //dest->writeField(wp,0x0,2); // Power reduction: 0
117 //dest->writeField(wp,TFI,5); // Temporary flow identifier
118 //dest->writeField(wp,0x1,1); // Direction
119
120 dest->writeField(wp,0x09,6); // MESSAGE TYPE
121 dest->writeField(wp,0x0,2); // Page Mode
122
123 dest->writeField(wp,0x0,2);
124 dest->writeField(wp,TFI,5); // Uplink TFI
125 dest->writeField(wp,0x0,1);
126
127 dest->writeField(wp,0x0,2); // CS1
128 if (CV == 0) dest->writeField(wp,0x1,1); // FINAL_ACK_INDICATION
129 else dest->writeField(wp,0x0,1); // FINAL_ACK_INDICATION
130 dest->writeField(wp,BSN+1,7); // STARTING_SEQUENCE_NUMBER
131 // RECEIVE_BLOCK_BITMAP
132 for (unsigned i=0; i<8; i++) {
133 dest->writeField(wp,0xff,8);
134 }
135 dest->writeField(wp,0x1,1); // CONTENTION_RESOLUTION_TLLI = present
136 dest->writeField(wp,TLLI,8*4);
137 dest->writeField(wp,0x00,4); //spare
138}
139
140void RLCMACDispatchMessage(BitVector *vector)
141{
142 static uint8_t rlc_data[60];
143 static uint8_t tfi = 0;
144 static uint32_t tlli = 0;
145 static unsigned dataIndex = 0;
146 static unsigned startDispatch = 0;
147 unsigned blockDataLen = 0;
148 unsigned readIndex = 0;
149 unsigned payload = vector->readField(readIndex, 2);
150
151 switch (payload) {
152 case RLCMAC_DATA_BLOCK:
153 {
154 COUT("RLCMAC_DATA_BLOCK<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
155 RlcMacUplinkDataBlock_t * dataBlock = (RlcMacUplinkDataBlock_t *)malloc(sizeof(RlcMacUplinkDataBlock_t));
156 decode_gsm_rlcmac_uplink_data(vector, dataBlock);
157 COUT("RLCMAC_DATA_BLOCK_END------------------------------");
158 //TODO Implement other cases.
159 if (dataBlock->BSN == 0)
160 {
161 startDispatch = 1;
162 }
163 if (startDispatch)
164 {
165 tfi = dataBlock->TFI;
166 if (dataBlock->E_1 == 0) // Extension octet follows immediately
167 {
168 blockDataLen = dataBlock->LENGTH_INDICATOR[0];
169 }
170 else
171 {
172 blockDataLen = 20;
173 if(dataBlock->TI == 1) // TLLI field is present
174 {
175 tlli = dataBlock->TLLI;
176 blockDataLen -= 4;
177 if (dataBlock->PI == 1) // PFI is present if TI field indicates presence of TLLI
178 {
179 blockDataLen -= 1;
180 }
181 }
182 }
183 unsigned dataOctetNum = 0;
184 for (unsigned i = dataIndex; i < dataIndex + blockDataLen; i++)
185 {
186 rlc_data[i] = dataBlock->RLC_DATA[dataOctetNum];
187 dataOctetNum++;
188 }
189 dataIndex += blockDataLen;
190 BitVector packetUplinkAck(23*8);
191 packetUplinkAck.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
192 writePUack(&packetUplinkAck, tfi, tlli, dataBlock->CV, dataBlock->BSN);
193 COUT("RLCMAC_CONTROL_BLOCK>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
194 RlcMacDownlink_t * pUA = (RlcMacDownlink_t *)malloc(sizeof(RlcMacUplink_t));
195 decode_gsm_rlcmac_downlink(&packetUplinkAck, pUA);
196 free(pUA);
197 COUT("RLCMAC_CONTROL_BLOCK_END------------------------------");
198 sendToOpenBTS(&packetUplinkAck);
199 }
200 if (dataBlock->CV == 0)
201 {
202 sendToSGSN(tfi, tlli, rlc_data, dataIndex);
203 dataIndex = 0;
204 startDispatch = 0;
205 }
206 free(dataBlock);
207 }
208 break;
209 case RLCMAC_CONTROL_BLOCK:
210 {
211 COUT("RLCMAC_CONTROL_BLOCK<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
212 RlcMacUplink_t * controlBlock = (RlcMacUplink_t *)malloc(sizeof(RlcMacUplink_t));
213 decode_gsm_rlcmac_uplink(vector, controlBlock);
214 free(controlBlock);
215 COUT("RLCMAC_CONTROL_BLOCK_END------------------------------");
216 }
217 break;
218 default:
219 COUT("Unknown RLCMAC block payload\n");
220 }
221}
222
223void *RLCMACSocket(void *)
224{
225 BitVector *vector = new BitVector(23*8);
226 GPRSRLCMACSocket.nonblocking();
227 while (1) {
228 char buf[MAX_UDP_LENGTH];
229 int count = GPRSRLCMACSocket.read(buf, 3000);
230 if (count>0) {
231 vector->unpack((const unsigned char*)buf);
232 COUT("Recieve from OpenBTS (MS): " << *vector);
233 RLCMACDispatchMessage(vector);
234 }
235 }
236}