|
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ |
|
2 /* vim: set ts=2 et sw=2 tw=80: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef mozilla_dom_bluetooth_bluetoothoppmanager_h__ |
|
8 #define mozilla_dom_bluetooth_bluetoothoppmanager_h__ |
|
9 |
|
10 #include "BluetoothCommon.h" |
|
11 #include "BluetoothProfileManagerBase.h" |
|
12 #include "BluetoothSocketObserver.h" |
|
13 #include "DeviceStorage.h" |
|
14 #include "mozilla/dom/ipc/Blob.h" |
|
15 #include "mozilla/ipc/UnixSocket.h" |
|
16 #include "nsCOMArray.h" |
|
17 |
|
18 class nsIOutputStream; |
|
19 class nsIInputStream; |
|
20 class nsIVolumeMountLock; |
|
21 |
|
22 BEGIN_BLUETOOTH_NAMESPACE |
|
23 |
|
24 class BluetoothSocket; |
|
25 class ObexHeaderSet; |
|
26 class SendFileBatch; |
|
27 |
|
28 class BluetoothOppManager : public BluetoothSocketObserver |
|
29 , public BluetoothProfileManagerBase |
|
30 { |
|
31 public: |
|
32 BT_DECL_PROFILE_MGR_BASE |
|
33 virtual void GetName(nsACString& aName) |
|
34 { |
|
35 aName.AssignLiteral("OPP"); |
|
36 } |
|
37 |
|
38 static const int MAX_PACKET_LENGTH = 0xFFFE; |
|
39 |
|
40 virtual ~BluetoothOppManager(); |
|
41 static BluetoothOppManager* Get(); |
|
42 void ClientDataHandler(mozilla::ipc::UnixSocketRawData* aMessage); |
|
43 void ServerDataHandler(mozilla::ipc::UnixSocketRawData* aMessage); |
|
44 |
|
45 bool Listen(); |
|
46 |
|
47 bool SendFile(const nsAString& aDeviceAddress, BlobParent* aActor); |
|
48 bool SendFile(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob); |
|
49 bool StopSendingFile(); |
|
50 bool ConfirmReceivingFile(bool aConfirm); |
|
51 |
|
52 void SendConnectRequest(); |
|
53 void SendPutHeaderRequest(const nsAString& aFileName, int aFileSize); |
|
54 void SendPutRequest(uint8_t* aFileBody, int aFileBodyLength); |
|
55 void SendPutFinalRequest(); |
|
56 void SendDisconnectRequest(); |
|
57 |
|
58 void ExtractPacketHeaders(const ObexHeaderSet& aHeader); |
|
59 bool ExtractBlobHeaders(); |
|
60 void CheckPutFinal(uint32_t aNumRead); |
|
61 |
|
62 // The following functions are inherited from BluetoothSocketObserver |
|
63 void ReceiveSocketData( |
|
64 BluetoothSocket* aSocket, |
|
65 nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE; |
|
66 virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE; |
|
67 virtual void OnSocketConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE; |
|
68 virtual void OnSocketDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE; |
|
69 |
|
70 private: |
|
71 BluetoothOppManager(); |
|
72 bool Init(); |
|
73 void HandleShutdown(); |
|
74 |
|
75 void StartFileTransfer(); |
|
76 void StartSendingNextFile(); |
|
77 void FileTransferComplete(); |
|
78 void UpdateProgress(); |
|
79 void ReceivingFileConfirmation(); |
|
80 bool CreateFile(); |
|
81 bool WriteToFile(const uint8_t* aData, int aDataLength); |
|
82 void DeleteReceivedFile(); |
|
83 void ReplyToConnect(); |
|
84 void ReplyToDisconnectOrAbort(); |
|
85 void ReplyToPut(bool aFinal, bool aContinue); |
|
86 void ReplyError(uint8_t aError); |
|
87 void AfterOppConnected(); |
|
88 void AfterFirstPut(); |
|
89 void AfterOppDisconnected(); |
|
90 void ValidateFileName(); |
|
91 bool IsReservedChar(char16_t c); |
|
92 void ClearQueue(); |
|
93 void RetrieveSentFileName(); |
|
94 void NotifyAboutFileChange(); |
|
95 bool AcquireSdcardMountLock(); |
|
96 void SendObexData(uint8_t* aData, uint8_t aOpcode, int aSize); |
|
97 void AppendBlobToSend(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob); |
|
98 void DiscardBlobsToSend(); |
|
99 bool ProcessNextBatch(); |
|
100 void ConnectInternal(const nsAString& aDeviceAddress); |
|
101 |
|
102 /** |
|
103 * Usually we won't get a full PUT packet in one operation, which means that |
|
104 * a packet may be devided into several parts and BluetoothOppManager should |
|
105 * be in charge of assembling. |
|
106 * |
|
107 * @return true if a packet has been fully received. |
|
108 * false if the received length exceeds/not reaches the expected |
|
109 * length. |
|
110 */ |
|
111 bool ComposePacket(uint8_t aOpCode, |
|
112 mozilla::ipc::UnixSocketRawData* aMessage); |
|
113 |
|
114 /** |
|
115 * OBEX session status. |
|
116 * Set when OBEX session is established. |
|
117 */ |
|
118 bool mConnected; |
|
119 nsString mConnectedDeviceAddress; |
|
120 |
|
121 /** |
|
122 * Remote information |
|
123 */ |
|
124 uint8_t mRemoteObexVersion; |
|
125 uint8_t mRemoteConnectionFlags; |
|
126 int mRemoteMaxPacketLength; |
|
127 |
|
128 /** |
|
129 * For sending files, we decide our next action based on current command and |
|
130 * previous one. |
|
131 * For receiving files, we don't need previous command and it is set to 0 |
|
132 * as a default value. |
|
133 */ |
|
134 int mLastCommand; |
|
135 |
|
136 int mPacketLength; |
|
137 int mPutPacketReceivedLength; |
|
138 int mBodySegmentLength; |
|
139 int mUpdateProgressCounter; |
|
140 |
|
141 /** |
|
142 * When it is true and the target service on target device couldn't be found, |
|
143 * refreshing SDP records is necessary. |
|
144 */ |
|
145 bool mNeedsUpdatingSdpRecords; |
|
146 |
|
147 /** |
|
148 * Set when StopSendingFile() is called. |
|
149 */ |
|
150 bool mAbortFlag; |
|
151 |
|
152 /** |
|
153 * Set when receiving the first PUT packet of a new file |
|
154 */ |
|
155 bool mNewFileFlag; |
|
156 |
|
157 /** |
|
158 * Set when receiving a PutFinal packet |
|
159 */ |
|
160 bool mPutFinalFlag; |
|
161 |
|
162 /** |
|
163 * Set when FileTransferComplete() is called |
|
164 */ |
|
165 bool mSendTransferCompleteFlag; |
|
166 |
|
167 /** |
|
168 * Set when a transfer is successfully completed. |
|
169 */ |
|
170 bool mSuccessFlag; |
|
171 |
|
172 /** |
|
173 * True: Receive file (Server) |
|
174 * False: Send file (Client) |
|
175 */ |
|
176 bool mIsServer; |
|
177 |
|
178 /** |
|
179 * Set when receiving the first PUT packet and wait for |
|
180 * ConfirmReceivingFile() to be called. |
|
181 */ |
|
182 bool mWaitingForConfirmationFlag; |
|
183 |
|
184 nsString mFileName; |
|
185 nsString mContentType; |
|
186 uint32_t mFileLength; |
|
187 uint32_t mSentFileLength; |
|
188 bool mWaitingToSendPutFinal; |
|
189 |
|
190 nsAutoArrayPtr<uint8_t> mBodySegment; |
|
191 nsAutoArrayPtr<uint8_t> mReceivedDataBuffer; |
|
192 |
|
193 int mCurrentBlobIndex; |
|
194 nsCOMPtr<nsIDOMBlob> mBlob; |
|
195 nsTArray<SendFileBatch> mBatches; |
|
196 |
|
197 /** |
|
198 * A seperate member thread is required because our read calls can block |
|
199 * execution, which is not allowed to happen on the IOThread. |
|
200 */ |
|
201 nsCOMPtr<nsIThread> mReadFileThread; |
|
202 nsCOMPtr<nsIOutputStream> mOutputStream; |
|
203 nsCOMPtr<nsIInputStream> mInputStream; |
|
204 nsCOMPtr<nsIVolumeMountLock> mMountLock; |
|
205 nsRefPtr<DeviceStorageFile> mDsFile; |
|
206 |
|
207 // If a connection has been established, mSocket will be the socket |
|
208 // communicating with the remote socket. We maintain the invariant that if |
|
209 // mSocket is non-null, mRfcommSocket and mL2capSocket must be null (and vice |
|
210 // versa). |
|
211 nsRefPtr<BluetoothSocket> mSocket; |
|
212 |
|
213 // Server sockets. Once an inbound connection is established, it will hand |
|
214 // over the ownership to mSocket, and get a new server socket while Listen() |
|
215 // is called. |
|
216 nsRefPtr<BluetoothSocket> mRfcommSocket; |
|
217 nsRefPtr<BluetoothSocket> mL2capSocket; |
|
218 }; |
|
219 |
|
220 END_BLUETOOTH_NAMESPACE |
|
221 |
|
222 #endif |