Merge lp:~morphis/aethercast/hw-encoding-support into lp:aethercast
- hw-encoding-support
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~morphis/aethercast/hw-encoding-support |
Merge into: | lp:aethercast |
Diff against target: |
20104 lines (+9512/-8610) 158 files modified
CMakeLists.txt (+16/-4) conf/CMakeLists.txt (+3/-0) conf/aethercast.conf.in (+14/-1) conf/dhcpd.conf (+5/-0) data/fi.w1.wpa_supplicant1.xml (+109/-0) debian/aethercast.install (+1/-0) debian/control (+3/-0) debian/rules (+3/-0) debian/usr.sbin.aethercast (+11/-0) src/CMakeLists.txt (+52/-16) src/client/application.cpp (+8/-3) src/mcs/android/fileoutputtarget.cpp (+55/-0) src/mcs/android/fileoutputtarget.h (+42/-0) src/mcs/android/h264encoder.cpp (+160/-0) src/mcs/android/h264encoder.h (+77/-0) src/mcs/android/pipedoutputtarget.cpp (+54/-0) src/mcs/android/pipedoutputtarget.h (+42/-0) src/mcs/basesourcemediamanager.cpp (+20/-13) src/mcs/basesourcemediamanager.h (+1/-0) src/mcs/config.h.in (+8/-8) src/mcs/dbushelpers.cpp (+46/-3) src/mcs/dbushelpers.h (+9/-2) src/mcs/forwardingmiracastcontroller.cpp (+2/-2) src/mcs/forwardingmiracastcontroller.h (+1/-1) src/mcs/forwardingnetworkdevice.cpp (+0/-51) src/mcs/forwardingnetworkdevice.h (+0/-42) src/mcs/gobject_deleter.h (+2/-0) src/mcs/gstsourcemediamanager.cpp (+11/-1) src/mcs/initgstreameronce.cpp (+88/-0) src/mcs/initgstreameronce.h (+29/-0) src/mcs/mediamanagerfactory.cpp (+6/-3) src/mcs/mir/sourcemediamanager.cpp (+37/-88) src/mcs/mir/sourcemediamanager.h (+14/-6) src/mcs/miracastcontroller.h (+2/-1) src/mcs/miracastcontrollerskeleton.cpp (+1/-4) src/mcs/miracastservice.cpp (+61/-16) src/mcs/miracastservice.h (+4/-1) src/mcs/miracastsourceclient.cpp (+1/-1) src/mcs/miracastsourcemanager.cpp (+3/-3) src/mcs/networkdevice.cpp (+3/-3) src/mcs/networkdeviceskeleton.cpp (+0/-142) src/mcs/networkmanager.cpp (+10/-0) src/mcs/networkmanager.h (+12/-2) src/mcs/networkmanagerfactory.cpp (+69/-6) src/mcs/networkmanagerfactory.h (+21/-0) src/mcs/networkutils.cpp (+21/-0) src/mcs/networkutils.h (+1/-0) src/mcs/testsourcemediamanager.cpp (+29/-4) src/mcs/utils.cpp (+14/-0) src/mcs/utils.h (+8/-0) src/mcs/videoformat.cpp (+383/-0) src/mcs/videoformat.h (+43/-0) src/mcs/x11sourcemediamanager.cpp (+51/-0) src/mcs/x11sourcemediamanager.h (+38/-0) src/mcs/x264.cpp (+206/-0) src/mcs/x264.h (+82/-0) src/w11t/commandqueue.cpp (+0/-103) src/w11t/commandqueue.h (+0/-63) src/w11t/dhcpclient.cpp (+0/-102) src/w11t/dhcpserver.cpp (+0/-99) src/w11t/gdhcp/client.c (+0/-3282) src/w11t/gdhcp/common.c (+0/-780) src/w11t/gdhcp/common.h (+0/-220) src/w11t/gdhcp/gdhcp.h (+0/-244) src/w11t/gdhcp/ipv4ll.c (+0/-135) src/w11t/gdhcp/ipv4ll.h (+0/-55) src/w11t/gdhcp/server.c (+0/-934) src/w11t/gdhcp/unaligned.h (+0/-163) src/w11t/message.cpp (+0/-128) src/w11t/message.h (+0/-203) src/w11t/networkdevice.cpp (+0/-67) src/w11t/networkdevice.h (+0/-54) src/w11t/networkmanager.cpp (+0/-740) src/w11t/networkmanager.h (+0/-121) src/w11t/wfddeviceinfo.cpp (+0/-74) src/w11t/wfddeviceinfo.h (+0/-65) src/w11tng/config.h.in (+8/-18) src/w11tng/dhcpclient.cpp (+112/-0) src/w11tng/dhcpclient.h (+71/-0) src/w11tng/dhcpleaseparser.cpp (+130/-0) src/w11tng/dhcpleaseparser.h (+29/-36) src/w11tng/dhcpserver.cpp (+129/-0) src/w11tng/dhcpserver.h (+30/-23) src/w11tng/filemonitor.cpp (+74/-0) src/w11tng/filemonitor.h (+60/-0) src/w11tng/hostname1stub.cpp (+136/-0) src/w11tng/hostname1stub.h (+73/-0) src/w11tng/informationelement.cpp (+171/-0) src/w11tng/informationelement.h (+165/-0) src/w11tng/interfaceselector.cpp (+125/-0) src/w11tng/interfaceselector.h (+66/-0) src/w11tng/interfacestub.cpp (+95/-0) src/w11tng/interfacestub.h (+69/-0) src/w11tng/managerstub.cpp (+202/-0) src/w11tng/managerstub.h (+83/-0) src/w11tng/netlinklistener.cpp (+205/-0) src/w11tng/netlinklistener.h (+64/-0) src/w11tng/networkdevice.cpp (+126/-0) src/w11tng/networkdevice.h (+92/-0) src/w11tng/networkmanager.cpp (+645/-0) src/w11tng/networkmanager.h (+153/-0) src/w11tng/p2pdevicestub.cpp (+447/-0) src/w11tng/p2pdevicestub.h (+112/-0) src/w11tng/peerstub.cpp (+165/-0) src/w11tng/peerstub.h (+77/-0) src/w11tng/processexecutor.cpp (+102/-0) src/w11tng/processexecutor.h (+56/-0) src/w11tng/wififirmwareloader.cpp (+6/-3) src/w11tng/wififirmwareloader.h (+4/-2) tests/3rd_party/lxc-nl/CMakeLists.txt (+6/-0) tests/3rd_party/lxc-nl/network.c (+308/-0) tests/3rd_party/lxc-nl/network.h (+34/-0) tests/3rd_party/lxc-nl/nl.c (+313/-0) tests/3rd_party/lxc-nl/nl.h (+260/-0) tests/CMakeLists.txt (+15/-3) tests/common/dbusfixture.cpp (+190/-0) tests/common/dbusfixture.h (+67/-0) tests/common/dbusnameowner.cpp (+43/-0) tests/common/dbusnameowner.h (+44/-0) tests/common/glibhelpers.cpp (+43/-0) tests/common/glibhelpers.h (+34/-0) tests/common/virtualnetwork.cpp (+56/-0) tests/common/virtualnetwork.h (+42/-0) tests/mcs/CMakeLists.txt (+4/-4) tests/mcs/acceptance_tests/CMakeLists.txt (+0/-2) tests/mcs/forwardingmiracastcontroller_tests.cpp (+3/-3) tests/mcs/forwardingnetworkdevice_tests.cpp (+0/-50) tests/mcs/mediamanagerfactory_tests.cpp (+3/-3) tests/mcs/miracastcontrollerskeleton_tests.cpp (+3/-3) tests/mcs/mock_network_device.h (+0/-35) tests/mcs/networkdevice_tests.cpp (+0/-36) tests/mcs/networkdeviceskeleton_tests.cpp (+0/-51) tests/mcs/networkmanagerfactory_tests.cpp (+44/-0) tests/mcs/x264_tests.cpp (+86/-0) tests/scoped_gobject_tests.cpp (+1/-0) tests/w11t/CMakeLists.txt (+0/-7) tests/w11t/wfddeviceinfo_test.cpp (+0/-38) tests/w11t/wpasupplicantcommandqueue_test.cpp (+0/-108) tests/w11t/wpasupplicantmessage_test.cpp (+0/-126) tests/w11tng/CMakeLists.txt (+14/-0) tests/w11tng/baseskeleton.cpp (+58/-0) tests/w11tng/baseskeleton.h (+49/-0) tests/w11tng/dhcp_tests.cpp (+66/-0) tests/w11tng/dhcpleaseparser_tests.cpp (+93/-0) tests/w11tng/informationelement_tests.cpp (+62/-0) tests/w11tng/interfaceselector_tests.cpp (+158/-0) tests/w11tng/interfaceskeleton.cpp (+43/-0) tests/w11tng/interfaceskeleton.h (+45/-0) tests/w11tng/interfacestub_tests.cpp (+75/-0) tests/w11tng/netlinklistener_tests.cpp (+67/-0) tests/w11tng/p2pdeviceskeleton.cpp (+137/-0) tests/w11tng/p2pdeviceskeleton.h (+72/-0) tests/w11tng/p2pdevicestub_tests.cpp (+192/-0) tests/w11tng/peerskeleton.cpp (+40/-0) tests/w11tng/peerskeleton.h (+44/-0) tests/w11tng/peerstub_tests.cpp (+73/-0) tools/CMakeLists.txt (+25/-0) tools/mirscreencast_to_android_hw_enc.cpp (+526/-0) |
To merge this branch: | bzr merge lp:~morphis/aethercast/hw-encoding-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phablet Team | Pending | ||
Review via email: mp+284112@code.launchpad.net |
This proposal has been superseded by a proposal from 2016-01-27.
Commit message
Description of the change
Add HW encoding support
- 137. By Simon Fels
-
Abstract mir stream connection behind a connector
- 138. By Simon Fels
-
Add stream renderer which gets frames from mir and sends them to the encoder
- 139. By Simon Fels
-
Integrate stream renderer with miracast source manager
- 140. By Simon Fels
-
Make d'tor of base class correctly virtual
- 141. By Simon Fels
-
Force mir as default media manager
- 142. By Simon Fels
-
Add missing return type for function
- 143. By Simon Fels
-
Extended debugging output for mir source manager
- 144. By Simon Fels
-
All changes to get streaming working
- 145. By Simon Fels
-
Add support to retrieve raw output from the encoder
- 146. By Simon Fels
-
Actually stop the stream renderer on destruction
- 147. By Simon Fels
-
Set H264 profile/
level/constrain t for encoder - 148. By Simon Fels
-
Make sure the encoder os properly initialized before starting
- 149. By Simon Fels
-
Take raw h264 frames from encoder as input for the pipeline
- 150. By Simon Fels
-
Check for possible errors on encoder construction
- 151. By Simon Fels
-
Don't call not existing libmedia API method for now
- 152. By Simon Fels
-
Construct pipeline with parse/mux/pay elements
- 153. By Simon Fels
-
Limit what resolutions, fps, codec parameters we can provide
- 154. By Simon Fels
-
Raise our GO intent to always become the group owner
- 155. By Simon Fels
-
Drop superflous pipeline state change
- 156. By Simon Fels
-
Dump the actual framerate we're recording with from mir
- 157. By Simon Fels
-
Drop h264parse element and just use caps
- 158. By Simon Fels
-
Simply mirscreencast utility to just dump to a file
- 159. By Simon Fels
-
Add queue elements for extended buffering
- 160. By Simon Fels
-
Add proper .gitignore file
- 161. By Simon Fels
-
Take buffers from android and put them into Gstreamer ones
- 162. By Simon Fels
-
Add utility to use plain streaming for testing
- 163. By Simon Fels
-
tools: stream: start source on startup
- 164. By Simon Fels
-
tools: screencast: initialize gstreamer on startup
- 165. By Simon Fels
-
tools: stream: run forever and react on SIGINT/SIGTERM
- 166. By Simon Fels
-
Include current thread id in each log message
- 167. By Simon Fels
-
Only submit buffers to the pipeline when its ready for new ones
If we're producing buffers at a too hight rate we're getting them with
incorrect timestamps into the pipeline which leads to delays on the
receiver side because PCR/PTS of the MPEGTS stream doesn't match anymore.This will be further optimized.
- 168. By Simon Fels
-
Ignore unused function parameters
- 169. By Simon Fels
-
Drop superflous debug statements
- 170. By Simon Fels
-
Add dirty option to dump the stream rather than sending it out
- 171. By Simon Fels
-
Link source and mux together with a pad to specify the MPEGTS PID
The WiFi Display spec requires us to send the video stream on a
specific PID (0x1011) which we can request to the mpegtsmux
element by request a pad with a specific name. - 172. By Simon Fels
-
mir: simply pad request/link for mpegtsmux element
- 173. By Simon Fels
-
Drop changed PMT/PAT intervals
- 174. By Simon Fels
-
Comment on how we're requesting a different stream PID
- 175. By Simon Fels
-
Switch to nal alignment
- 176. By Simon Fels
-
Merge branch 'trunk' into hw-encoding-support
- 177. By Simon Fels
-
Merge trunk
- 178. By Simon Fels
-
Add missing files lost due to a failed merge with trunk
- 179. By Simon Fels
-
Request 188 byte length packages from MPEGTS element
- 180. By Simon Fels
-
debian: add missing build depends
- 181. By Simon Fels
-
debian: add missing libgstreamer-
plugins- base1.0- dev dependency - 182. By Simon Fels
-
Fail when pipeline can't be configured
- 183. By Simon Fels
-
Add support for an extended display
- 184. By Simon Fels
-
Correct vertex position data to use the full screen
- 185. By Simon Fels
-
Draw white background so we're able to discover empty fragments
- 186. By Simon Fels
-
Add base encoder class and start a H264EncoderNext implementation
- 187. By Simon Fels
-
Print out timestamps for performance analysis
- 188. By Simon Fels
-
Refactor encoder integration and finalize new H264 implementation
- 189. By Simon Fels
-
Make new h264 encoder working properly
- 190. By Simon Fels
-
Tune default encoder values to follow what Android does for WFD
- 191. By Simon Fels
-
Implement MPEGTS packetizer
Based on the implementation from Android.
- 192. By Simon Fels
-
Optimizer buffer timestamps and encoder configuration
- 193. By Simon Fels
-
Adding missing encoder config field
- 194. By Simon Fels
-
A lot more work on getting rid of gstreamer
Adding own RTP sender implementation which is now properly used
from a new source media manager type called 'mir-next'.This also refactors some parts of the already existing code.
- 195. By Simon Fels
-
Drop accidentially added code
- 196. By Simon Fels
-
Enable dumping of the MPEGTS stream
- 197. By Simon Fels
-
Extract codec specific data and prepend to AVC buffers
- 198. By Simon Fels
-
Be less verbose for encoder output
- 199. By Simon Fels
-
Tell MPEGTS packetizer to include SPS/PPS with IDR frames
- 200. By Simon Fels
-
Add utility method to create a hexdump
- 201. By Simon Fels
-
Take SPS/PPS from codec data when available
- 202. By Simon Fels
-
Add H264 analyzer to collect statistics
- 203. By Simon Fels
-
Don't tell the MPEGST packtizer to add SPS/PPS to IDR frames
- 204. By Simon Fels
-
Let encoder submit buffer with codec-specific data for transmission
- 205. By Simon Fels
-
Add output to measure performance
- 206. By Simon Fels
-
Pass local address down to our WDS delegate
We need to transmit our local address correctly within the RTSP
message we're exchanging with the other side which we missed
until now. - 207. By Simon Fels
-
Extract timestamp from buffer we get from the encoder
- 208. By Simon Fels
-
Use proper constants for encoder configuration
- 209. By Simon Fels
-
Increase video bitrate to have a stable picture
- 210. By Simon Fels
-
Check for valid meta data structure before accessing it
- 211. By Simon Fels
-
Don't set buffer timestamp manually
- 212. By Simon Fels
-
Let encoder include SPS/PPS with each IDR frame
- 213. By Simon Fels
-
Ask encoder to store meta data in buffers
- 214. By Simon Fels
-
Adjust for WDS 1.0.0 API changes
- 215. By Simon Fels
-
MPEGTS packetizer fixes
- 216. By Simon Fels
-
Raise our process priority
- 217. By Simon Fels
-
Revert try to move buffer timestamp ahead
- 218. By Simon Fels
-
Add a proper buffer queue for Media/RTP sender
- 219. By Simon Fels
-
Add a measure point abstraction class
- 220. By Simon Fels
-
Decouple texture creation and rendering
- 221. By Simon Fels
-
Add missing macro
- 222. By Simon Fels
-
But add the macro at the right place
- 223. By Simon Fels
-
Work with a not-blocking socket
- 224. By Simon Fels
-
Revert buffer queue for stream renderer
- 225. By Simon Fels
-
Force GO intent to 15 for now
- 226. By Simon Fels
-
Cleanup old H264Encoder instance
- 227. By Simon Fels
-
tools: let utility build again even if not functional now
- 228. By Simon Fels
-
android: first bits of the h264 encoder implementation
- 229. By Simon Fels
-
Implement new encoder which directly forwards native buffers from mir
- 230. By Simon Fels
-
Unblock input buffer queue when taking a buffer out
- 231. By Simon Fels
-
tools: mpegts_muxer: specifiy file open mode properly
- 232. By Simon Fels
-
tools: mirscreencast_
to_stream: add cmdline option to extend the display - 233. By Simon Fels
-
Pass dimensions correct to the screencast instance
- 234. By Simon Fels
-
Drop unneeded log message
- 235. By Simon Fels
-
Some further explaining comments
- 236. By Simon Fels
-
Fix syntax error in build configuration
- 237. By Simon Fels
-
Disable gstreamer initialization for now
- 238. By Simon Fels
-
Do an async swap buffers call to mir for direct rendering
- 239. By Simon Fels
-
Correct debug statement order
- 240. By Simon Fels
-
Optimize some more debug statements
- 241. By Simon Fels
-
Optimize buffer timestamp logging
We're only interested in how late we're with a buffer and nothing
else as that is what is causing our delay. - 242. By Simon Fels
-
Timestamp buffer directly after we received them
- 243. By Simon Fels
-
Further timestamp logging optimizations
- 244. By Simon Fels
-
Drop unneeded buffer refcount logging
- 245. By Simon Fels
-
Further timestamp logging adjustments
- 246. By Simon Fels
-
Drop two more unneeded debug log statements
- 247. By Simon Fels
-
Include now in timestamp logging
- 248. By Simon Fels
-
For stick to synchronously processing a single buffer
- 249. By Simon Fels
-
Increase UDP send buffer size
- 250. By Simon Fels
-
Add type definitions for timestamps
- 251. By Simon Fels
-
Stop media sender and encoder too when pipeline goes down
- 252. By Simon Fels
-
Implement infrastructure for screen/system locks
- 253. By Simon Fels
-
Adjust buffer timestamp to respect our framerate
- 254. By Simon Fels
-
Further timestamp logging changes
- 255. By Simon Fels
-
Add cross compilation setup (copied from mir)
- 256. By Simon Fels
-
Add some more timestamp logging
- 257. By Simon Fels
-
Build with debug configuration
- 258. By Simon Fels
-
Don't check for matching buffer and just drop the queue head
- 259. By Simon Fels
-
Use a buffer queue for the renderer with a max size of two
- 260. By Simon Fels
-
Revert substracting a static offset from timestamps
- 261. By Simon Fels
-
Stop whole pipeline properly on termination
- 262. By Simon Fels
-
Correct apparmor rules for our dhcpd use
- 263. By Simon Fels
-
We only support extend mode for now
- 264. By Simon Fels
-
Properly terminate pipeline for the stream tool
- 265. By Simon Fels
-
Add some more statistics we collect over time
- 266. By Simon Fels
-
Ignore multiple build folders
- 267. By Simon Fels
-
Switch back to same UDP packet size Android uses
- 268. By Simon Fels
-
Printout a warning when we can't find a optimal video format
- 269. By Simon Fels
-
Bring GST based media manager in line with recent changes
- 270. By Simon Fels
-
Some more explanation comments
- 271. By Simon Fels
-
Fix test source media manager
- 272. By Simon Fels
-
Extend logger to be able to set severity on startup
- 273. By Simon Fels
-
Have a proper video format fallback instead of invalid values
- 274. By Simon Fels
-
Free GLib error messages once done with it
- 275. By Simon Fels
-
Let media buffer allocate the memory to transfer ownership
- 276. By Simon Fels
-
Implement DisconnectAll manager method
- 277. By Simon Fels
-
Add unit tests to verify wds video format selection
- 278. By Simon Fels
-
tools: install mirscreencast_
to_stream utility - 279. By Simon Fels
-
debian: package mirscreencast_
to_stream utility too - 280. By Simon Fels
-
debian: add a dependency on -tools for aethercast for now
- 281. By Simon Fels
-
Do correct video format negotiation
- 282. By Simon Fels
-
debian: install additional files we missed before
- 283. By Simon Fels
-
Disable power save mode of p2p network interface
- 284. By Simon Fels
-
Temporarily disable logging of buffer timestamps
- 285. By Simon Fels
-
debian: fix apparmor profile extension for dhcpd
- 286. By Simon Fels
-
Listen on all local addresses for incoming RTSP connection requests
- 287. By Simon Fels
-
Set GO intent to 7 and let user change that with an env variable
- 288. By Simon Fels
-
Setup a route when running as DHCP server
- 289. By Simon Fels
-
Select resolution based on env variable
- 290. By Simon Fels
-
Disable per timestamping according to framerate
- 291. By Simon Fels
-
Set names for our threads to be able to identify them
- 292. By Simon Fels
-
Save statistics for RTP bandwidth
- 293. By Simon Fels
-
Print out statistics when our source manager goes down
- 294. By Simon Fels
-
Don't produce more frames than we have to
- 295. By Simon Fels
-
Sent RTP packets directly to remote via sendto
- 296. By Simon Fels
-
Send all RTP packets a TS frames belongs too together
- 297. By Simon Fels
-
Allow remote to ask us for an IDR frame
- 298. By Simon Fels
-
Check mime type correctly for video/audio prefix
- 299. By Simon Fels
-
Correct RTP bandwidth statistics output
- 300. By Simon Fels
-
Refactor local address assignmnet for source manager
- 301. By Simon Fels
-
Enable driver side miracast mode on successful connection
- 302. By Simon Fels
-
Return an error for a failing scan call
- 303. By Simon Fels
-
Don't allow dhcpd to edit our configuration file
- 304. By Simon Fels
-
Add support for new wpa API method to send driver commands
- 305. By Simon Fels
-
debian: fix apparmor setup
* reload dhcpd profile on startup
* add DAC override for dhcpd to overcome a bug in its package - 306. By Simon Fels
-
Dump additional information for GO negotiation response
- 307. By Simon Fels
-
Pass correct arguments to dbus error message creation
- 308. By Simon Fels
-
Small adjustments to the connect logic
- 309. By Simon Fels
-
Limit us to only support 720p with 30 Hz for now
- 310. By Simon Fels
-
Print out group negotiation error for easier debugging
- 311. By Simon Fels
-
Format debug message correctly and supply all arguments
- 312. By Simon Fels
-
Workaround problems with WDS rate/resolution selection
- 313. By Simon Fels
-
Use plain sockets for RTP connection rather than GLib
- 314. By Simon Fels
-
Extend GetEnvValue function to be able to return a default value
- 315. By Simon Fels
-
Wind local RTP port up the stack and don't use a static one
- 316. By Simon Fels
-
Setup miracast source manager when we're connected and not earlier
- 317. By Simon Fels
-
Define DHCP server address on construction
- 318. By Simon Fels
-
Drop result argument for SendDriverCommand method
- 319. By Simon Fels
-
Lock the display when we're connecting until we get disconnected
- 320. By Simon Fels
-
Force IPv4 for our DHCP client
- 321. By Simon Fels
-
Improve renderer/encoder to really stream a constant framerate
Also optimizes logging in different parts of the code
- 322. By Simon Fels
-
Only support CBP with level 3.1 for now
- 323. By Simon Fels
-
Trying to resend RTP packages one time and then fail
- 324. By Simon Fels
-
Implement missing interface method
- 325. By Simon Fels
-
Adjust for WPA DBus API changes
- 326. By Simon Fels
-
Don't adjust interface powersave mode
- 327. By Simon Fels
-
Keep pointer to management wifi interface
- 328. By Simon Fels
-
Refactor code to send private driver commands a bit
- 329. By Simon Fels
-
Drop all code for the GL rendering code path which we don't need anymore
- 330. By Simon Fels
-
Missing changes for cmake configuration
- 331. By Simon Fels
-
Drop some more unused code fragments for logging
- 332. By Simon Fels
-
Small code cleanups
- 333. By Simon Fels
-
Drop unused gstreamer x264 encoder wrapper
- 334. By Simon Fels
-
Remove unused system power state controller
- 335. By Simon Fels
-
Drop unused unit tests
- 336. By Simon Fels
-
Fix encoder class
- 337. By Simon Fels
-
Add unit tests for buffer class
- 338. By Simon Fels
-
Add video format extraction tests (missing VESA/HH support)
- 339. By Simon Fels
-
Correctly release media buffer
- 340. By Simon Fels
-
Update WFD IE to indicate a session is not available when connected
- 341. By Simon Fels
-
Drop unnecessary dependencies
- 342. By Simon Fels
-
Move MediaSender into streaming namespace
- 343. By Simon Fels
-
Add interfaces for RTP sender / MPEGTS packetizer classes to make MediaSender testable
- 344. By Simon Fels
-
Add unit tests for media sender class
- 345. By Simon Fels
-
Add utility function to set thread name
- 346. By Simon Fels
-
Add unit test to make sure we're requesting PCR/PAT and PMT
Unmerged revisions
- 346. By Simon Fels
-
Add unit test to make sure we're requesting PCR/PAT and PMT
- 345. By Simon Fels
-
Add utility function to set thread name
- 344. By Simon Fels
-
Add unit tests for media sender class
- 343. By Simon Fels
-
Add interfaces for RTP sender / MPEGTS packetizer classes to make MediaSender testable
- 342. By Simon Fels
-
Move MediaSender into streaming namespace
- 341. By Simon Fels
-
Drop unnecessary dependencies
- 340. By Simon Fels
-
Update WFD IE to indicate a session is not available when connected
- 339. By Simon Fels
-
Correctly release media buffer
- 338. By Simon Fels
-
Add video format extraction tests (missing VESA/HH support)
- 337. By Simon Fels
-
Add unit tests for buffer class
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-12-10 06:47:03 +0000 |
3 | +++ CMakeLists.txt 2016-01-27 13:00:21 +0000 |
4 | @@ -58,12 +58,23 @@ |
5 | find_package(PkgConfig) |
6 | find_package(Threads) |
7 | |
8 | -pkg_check_modules(GLIB glib-2.0) |
9 | -pkg_check_modules(GIO gio-2.0) |
10 | -pkg_check_modules(GIO-UNIX gio-unix-2.0) |
11 | +pkg_check_modules(GLIB REQUIRED glib-2.0) |
12 | +pkg_check_modules(GIO REQUIRED gio-2.0) |
13 | +pkg_check_modules(GIO-UNIX REQUIRED gio-unix-2.0) |
14 | pkg_check_modules(GST REQUIRED gstreamer-1.0) |
15 | pkg_check_modules(WDS REQUIRED wds) |
16 | -pkg_check_modules(READLINE readline) |
17 | +# FIXME for the time being mir is required to do proper hardware |
18 | +# encoding on Android platforms. This will be refactored at some |
19 | +# point to be abstracted by gstreamer completely or made optional. |
20 | +pkg_check_modules(MIRCLIENT REQUIRED mirclient) |
21 | +# Same as mentioned above applies for the hybris and android |
22 | +# things below. |
23 | +pkg_check_modules(HYBRIS_MEDIA REQUIRED libmedia) |
24 | +pkg_check_modules(ANDROID_HEADERS REQUIRED android-headers) |
25 | +pkg_check_modules(EGL REQUIRED egl) |
26 | +pkg_check_modules(GLESV2 REQUIRED glesv2) |
27 | +add_definitions(-DMESA_EGL_NO_X11_HEADERS) |
28 | + |
29 | # Build with system gmock and embedded gtest |
30 | set (GMOCK_INCLUDE_DIR "/usr/include/gmock/include" CACHE PATH "gmock source include directory") |
31 | set (GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory") |
32 | @@ -78,3 +89,4 @@ |
33 | add_subdirectory(conf) |
34 | add_subdirectory(src) |
35 | add_subdirectory(tests) |
36 | +add_subdirectory(tools) |
37 | |
38 | === removed directory 'build' |
39 | === modified file 'conf/CMakeLists.txt' |
40 | --- conf/CMakeLists.txt 2015-12-10 10:17:57 +0000 |
41 | +++ conf/CMakeLists.txt 2016-01-27 13:00:21 +0000 |
42 | @@ -5,3 +5,6 @@ |
43 | |
44 | install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/aethercast-dbus.conf |
45 | DESTINATION /etc/dbus-1/system.d/) |
46 | + |
47 | +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dhcpd.conf |
48 | + DESTINATION /etc/aethercast/) |
49 | |
50 | === modified file 'conf/aethercast.conf.in' |
51 | --- conf/aethercast.conf.in 2015-12-10 10:17:57 +0000 |
52 | +++ conf/aethercast.conf.in 2016-01-27 13:00:21 +0000 |
53 | @@ -5,4 +5,17 @@ |
54 | |
55 | respawn |
56 | |
57 | -exec /usr/sbin/aethercast |
58 | +script |
59 | + if [ -x `which getprop` ] ; then |
60 | + iface=`getprop wifi.direct.interface` |
61 | + if [ "$iface" != "" ] ; then |
62 | + export AETHERCAST_DEDICATED_P2P_INTERFACE=$iface |
63 | + # FIXME this might not be true for all devices but it should |
64 | + # not cause any for those which doesn't need any firmware as |
65 | + # the Android WiFi firmware loader should just pass through |
66 | + export AETHERCAST_NEED_FIRMWARE=1 |
67 | + fi |
68 | + fi |
69 | + |
70 | + exec /usr/sbin/aethercast |
71 | +end script |
72 | |
73 | === added file 'conf/dhcpd.conf' |
74 | --- conf/dhcpd.conf 1970-01-01 00:00:00 +0000 |
75 | +++ conf/dhcpd.conf 2016-01-27 13:00:21 +0000 |
76 | @@ -0,0 +1,5 @@ |
77 | +subnet 192.168.7.0 netmask 255.255.255.0 { |
78 | + range 192.168.7.5 192.168.7.10; |
79 | + option subnet-mask 255.255.255.0; |
80 | + option broadcast-address 192.168.7.255; |
81 | +} |
82 | |
83 | === added file 'data/fi.w1.wpa_supplicant1.xml' |
84 | --- data/fi.w1.wpa_supplicant1.xml 1970-01-01 00:00:00 +0000 |
85 | +++ data/fi.w1.wpa_supplicant1.xml 2016-01-27 13:00:21 +0000 |
86 | @@ -0,0 +1,109 @@ |
87 | +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" |
88 | + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> |
89 | +<node> |
90 | + <interface name="fi.w1.wpa_supplicant1"> |
91 | + <method name="CreateInterface"> |
92 | + <arg name="args" type="a{sv}" direction="in"/> |
93 | + <arg name="path" type="o" direction="out"/> |
94 | + </method> |
95 | + <signal name="InterfaceAdded"> |
96 | + <arg name="path" type="o"/> |
97 | + <arg name="properties" type="a{sv}"/> |
98 | + </signal> |
99 | + <signal name="InterfaceRemoved"> |
100 | + <arg name="path" type="o"/> |
101 | + </signal> |
102 | + <property name="Interfaces" type="ao" access="read"/> |
103 | + <property name="Capabilities" type="as" access="read"/> |
104 | + <property name="WFDIEs" type="ay" access="readwrite"> |
105 | + <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/> |
106 | + </property> |
107 | + </interface> |
108 | + <interface name="fi.w1.wpa_supplicant1.Interface"> |
109 | + <property name="Capabilities" type="a{sv}" access="read"/> |
110 | + <property name="State" type="s" access="read"/> |
111 | + <property name="Ifname" type="s" access="read"/> |
112 | + <property name="Driver" type="s" access="read"/> |
113 | + </interface> |
114 | + <interface name="fi.w1.wpa_supplicant1.Interface.P2PDevice"> |
115 | + <method name="Find"> |
116 | + <arg name="args" type="a{sv}" direction="in"/> |
117 | + </method> |
118 | + <method name="StopFind"/> |
119 | + <method name="ExtendedListen"> |
120 | + <arg name="args" type="a{sv}" direction="in"/> |
121 | + </method> |
122 | + <method name="Connect"> |
123 | + <arg name="args" type="a{sv}" direction="in"/> |
124 | + <arg name="group" type="s" direction="out"/> |
125 | + </method> |
126 | + <method name="Cancel"/> |
127 | + <method name="Disconnect"/> |
128 | + <method name="Flush"/> |
129 | + <signal name="DeviceFound"> |
130 | + <arg name="path" type="o"/> |
131 | + </signal> |
132 | + <signal name="DeviceLost"> |
133 | + <arg name="path" type="o"/> |
134 | + </signal> |
135 | + <signal name="FindStopped"/> |
136 | + <signal name="GONegotiationSuccess"> |
137 | + <arg name="properties" type="a{sv}"/> |
138 | + </signal> |
139 | + <signal name="GONegotiationFailure"> |
140 | + <arg name="properties" type="a{sv}"/> |
141 | + </signal> |
142 | + <signal name="GroupStarted"> |
143 | + <arg name="properties" type="a{sv}"/> |
144 | + </signal> |
145 | + <signal name="GroupFinished"> |
146 | + <arg name="properties" type="a{sv}"/> |
147 | + </signal> |
148 | + <signal name="GroupFormationFailure"> |
149 | + <arg name="reason" type="s"/> |
150 | + </signal> |
151 | + <signal name="GONegotiationRequest"> |
152 | + <arg name="path" type="o"/> |
153 | + <arg name="dev_passwd_id" type="i"/> |
154 | + </signal> |
155 | + <property name="P2PDeviceConfig" type="a{sv}" access="readwrite"/> |
156 | + <property name="Peers" type="ao" access="read"/> |
157 | + </interface> |
158 | + <interface name="fi.w1.wpa_supplicant1.Peer"> |
159 | + <property name="DeviceName" type="s" access="read"/> |
160 | + <property name="Manufacturer" type="s" access="read"/> |
161 | + <property name="ModelName" type="s" access="read"/> |
162 | + <property name="ModelNumber" type="s" access="read"/> |
163 | + <property name="SerialNumber" type="s" access="read"/> |
164 | + <property name="PrimaryDeviceType" type="ay" access="read"/> |
165 | + <property name="config_method" type="q" access="read"/> |
166 | + <property name="level" type="i" access="read"/> |
167 | + <property name="devicecapability" type="y" access="read"/> |
168 | + <property name="groupcapability" type="y" access="read"/> |
169 | + <property name="SecondaryDeviceTypes" type="aay" access="read"/> |
170 | + <property name="VendorExtension" type="aay" access="read"/> |
171 | + <property name="IEs" type="ay" access="read"/> |
172 | + <property name="DeviceAddress" type="ay" access="read"> |
173 | + <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/> |
174 | + </property> |
175 | + <property name="Groups" type="ao" access="read"/> |
176 | + </interface> |
177 | + <interface name="fi.w1.wpa_supplicant1.Group"> |
178 | + <property name="Members" type="s" access="read"/> |
179 | + <property name="Group" type="o" access="read"/> |
180 | + <property name="Role" type="s" access="read"/> |
181 | + <property name="SSID" type="ay" access="read"/> |
182 | + <property name="BSSID" type="ay" access="read"/> |
183 | + <property name="Frequency" type="q" access="read"/> |
184 | + <property name="Passphrase" type="s" access="read"/> |
185 | + <property name="PSK" type="ay" access="read"/> |
186 | + <property name="WPSVendorExtensions" type="aay" access="read"/> |
187 | + <signal name="PeerJoined"> |
188 | + <arg name="peer" type="o"/> |
189 | + </signal> |
190 | + <signal name="PeerDisconnected"> |
191 | + <arg name="peer" type="o"/> |
192 | + </signal> |
193 | + </interface> |
194 | +</node> |
195 | + |
196 | |
197 | === added file 'debian/aethercast.install' |
198 | --- debian/aethercast.install 1970-01-01 00:00:00 +0000 |
199 | +++ debian/aethercast.install 2016-01-27 13:00:21 +0000 |
200 | @@ -0,0 +1,1 @@ |
201 | +debian/usr.sbin.aethercast /etc/apparmor.d/dhcpd.d/ |
202 | |
203 | === modified file 'debian/control' |
204 | --- debian/control 2015-12-10 06:47:03 +0000 |
205 | +++ debian/control 2016-01-27 13:00:21 +0000 |
206 | @@ -5,6 +5,7 @@ |
207 | XSBC-Original-Maintainer: Simon Fels <simon.fels@canonical.com> |
208 | Build-Depends: cmake, |
209 | debhelper (>= 9), |
210 | + dbus, |
211 | google-mock, |
212 | libboost-dev, |
213 | libboost-filesystem-dev, |
214 | @@ -31,6 +32,8 @@ |
215 | Architecture: any |
216 | Depends: ${misc:Depends}, |
217 | ${shlibs:Depends}, |
218 | + isc-dhcp-server, |
219 | + isc-dhcp-client, |
220 | wpasupplicant |
221 | Description: Display casting service |
222 | A management service for remote displays which it can stream the |
223 | |
224 | === modified file 'debian/rules' |
225 | --- debian/rules 2015-11-19 12:17:57 +0000 |
226 | +++ debian/rules 2016-01-27 13:00:21 +0000 |
227 | @@ -17,3 +17,6 @@ |
228 | |
229 | %: |
230 | dh $@ --parallel --fail-missing |
231 | + |
232 | +override_dh_auto_test: |
233 | + # disable |
234 | |
235 | === added file 'debian/usr.sbin.aethercast' |
236 | --- debian/usr.sbin.aethercast 1970-01-01 00:00:00 +0000 |
237 | +++ debian/usr.sbin.aethercast 2016-01-27 13:00:21 +0000 |
238 | @@ -0,0 +1,11 @@ |
239 | +# vim:syntax=apparmor |
240 | + |
241 | + # Allow aethercast to start dhcpd with its own configuration |
242 | + # file it needs to provide DHCP for groups it manages through |
243 | + # WiFi Direct. This need to stay as long as NetworkManager does |
244 | + # not has support for WiFi Direct and aethercast is using that. |
245 | + /etc/aethercast/dhcpd.conf r, |
246 | + # In addition aethercast will also point dhcpd to a private |
247 | + # lease/pid file |
248 | + /{,var/}run/aethercast/dhcpd.leases* lrw, |
249 | + /{,var/}run/aethercast/dhcpd.pid lrw, |
250 | |
251 | === modified file 'src/CMakeLists.txt' |
252 | --- src/CMakeLists.txt 2015-12-18 17:15:31 +0000 |
253 | +++ src/CMakeLists.txt 2016-01-27 13:00:21 +0000 |
254 | @@ -9,14 +9,33 @@ |
255 | --interface-prefix org.aethercast. |
256 | ${CMAKE_CURRENT_SOURCE_DIR}/../data/org.aethercast.xml) |
257 | |
258 | +execute_process(COMMAND ${GDBUS_CODEGEN_EXECUTABLE} |
259 | + --c-namespace WpaSupplicant |
260 | + --c-generate-object-manager |
261 | + --generate-c-code ${CMAKE_CURRENT_BINARY_DIR}/mcs/wpasupplicantinterface |
262 | + --interface-prefix fi.w1.wpa_supplicant1. |
263 | + ${CMAKE_CURRENT_SOURCE_DIR}/../data/fi.w1.wpa_supplicant1.xml) |
264 | + |
265 | # Make sure that generated header files can be found |
266 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/mcs) |
267 | |
268 | +set(AETHERCAST_DHCP_HELPER "/usr/sbin/aethercast-dhcp-helper") |
269 | +set(DHCP_SERVER_PATH "/usr/sbin/dhcpd") |
270 | +set(DHCP_CLIENT_PATH "/sbin/dhclient") |
271 | + |
272 | +configure_file(mcs/config.h.in mcs/config.h @ONLY) |
273 | +configure_file(w11tng/config.h.in w11tng/config.h @ONLY) |
274 | + |
275 | set(HEADERS |
276 | mcs/ip_v4_address.h |
277 | mcs/keep_alive.h |
278 | mcs/mac_address.h |
279 | mcs/types.h |
280 | + mcs/shared_gobject.h |
281 | + mcs/keep_alive.h |
282 | + |
283 | + mcs/config.h |
284 | + w11tng/config.h |
285 | ) |
286 | |
287 | set(SOURCES |
288 | @@ -24,10 +43,12 @@ |
289 | mcs/networkutils.cpp |
290 | mcs/mediamanagerfactory.cpp |
291 | mcs/basesourcemediamanager.cpp |
292 | + mcs/initgstreameronce.cpp |
293 | mcs/gstsourcemediamanager.cpp |
294 | mcs/testsourcemediamanager.cpp |
295 | + mcs/x11sourcemediamanager.cpp |
296 | + mcs/videoformat.cpp |
297 | mcs/logger.cpp |
298 | - mcs/mirsourcemediamanager.cpp |
299 | mcs/forwardingmiracastcontroller.cpp |
300 | mcs/forwardingnetworkdevice.cpp |
301 | mcs/miracastcontroller.cpp |
302 | @@ -38,24 +59,35 @@ |
303 | mcs/networkmanager.cpp |
304 | mcs/networkmanagerfactory.cpp |
305 | mcs/networkdevice.cpp |
306 | - |
307 | + mcs/x264.cpp |
308 | ${CMAKE_CURRENT_BINARY_DIR}/mcs/aethercastinterface.c |
309 | mcs/dbushelpers.cpp |
310 | mcs/networkdeviceskeleton.cpp |
311 | |
312 | - w11t/gdhcp/common.c |
313 | - w11t/gdhcp/ipv4ll.c |
314 | - w11t/gdhcp/server.c |
315 | - w11t/gdhcp/client.c |
316 | - w11t/dhcpclient.cpp |
317 | - w11t/dhcpserver.cpp |
318 | - w11t/wififirmwareloader.cpp |
319 | - w11t/wfddeviceinfo.cpp |
320 | - w11t/message.cpp |
321 | - w11t/command.cpp |
322 | - w11t/commandqueue.cpp |
323 | - w11t/networkdevice.cpp |
324 | - w11t/networkmanager.cpp |
325 | + mcs/mir/sourcemediamanager.cpp |
326 | + |
327 | + mcs/android/h264encoder.cpp |
328 | + mcs/android/pipedoutputtarget.cpp |
329 | + mcs/android/fileoutputtarget.cpp |
330 | + |
331 | + ${CMAKE_CURRENT_BINARY_DIR}/mcs/wpasupplicantinterface.c |
332 | + w11tng/networkmanager.cpp |
333 | + w11tng/networkdevice.cpp |
334 | + w11tng/interfaceselector.cpp |
335 | + w11tng/p2pdevicestub.cpp |
336 | + w11tng/managerstub.cpp |
337 | + w11tng/peerstub.cpp |
338 | + w11tng/interfacestub.cpp |
339 | + w11tng/groupstub.cpp |
340 | + w11tng/informationelement.cpp |
341 | + w11tng/dhcpleaseparser.cpp |
342 | + w11tng/dhcpclient.cpp |
343 | + w11tng/dhcpserver.cpp |
344 | + w11tng/processexecutor.cpp |
345 | + w11tng/filemonitor.cpp |
346 | + w11tng/netlinklistener.cpp |
347 | + w11tng/wififirmwareloader.cpp |
348 | + w11tng/hostname1stub.cpp |
349 | ) |
350 | |
351 | link_directories( |
352 | @@ -63,6 +95,7 @@ |
353 | ${GIO_LIBRARY_DIRS} |
354 | ${GIO-UNIX_LIBRARY_DIRS} |
355 | ${WDS_LIBRARY_DIRS} |
356 | + ${HYBRIS_MEDIA_LIBRARY_DIRS} |
357 | ) |
358 | |
359 | include_directories( |
360 | @@ -72,8 +105,10 @@ |
361 | ${GIO-UNIX_INCLUDE_DIRS} |
362 | ${GST_INCLUDE_DIRS} |
363 | ${WDS_INCLUDE_DIRS} |
364 | - ${CMAKE_CURRENT_SOURCE_DIR}/w11t/gdhcp |
365 | + ${HYBRIS_MEDIA_INCLDUE_DIRS} |
366 | + ${ANDROID_HEADERS_INCLUDE_DIRS} |
367 | ${CMAKE_CURRENT_BINARY_DIR}/src |
368 | + ${CMAKE_CURRENT_BINARY_DIR}/src/w11tng |
369 | ) |
370 | |
371 | add_library(aethercast-core ${SOURCES} ${HEADERS}) |
372 | @@ -88,6 +123,7 @@ |
373 | ${GST_LIBRARIES} |
374 | ${CMAKE_THREAD_LIBS_INIT} |
375 | ${WDS_LIBRARIES} |
376 | + ${HYBRIS_MEDIA_LIBRARIES} |
377 | -ldl |
378 | ) |
379 | |
380 | |
381 | === modified file 'src/client/application.cpp' |
382 | --- src/client/application.cpp 2015-12-16 06:47:41 +0000 |
383 | +++ src/client/application.cpp 2016-01-27 13:00:21 +0000 |
384 | @@ -31,6 +31,9 @@ |
385 | |
386 | using namespace std::placeholders; |
387 | |
388 | +namespace { |
389 | +const unsigned int kDBusTimeout = 120; |
390 | + |
391 | class PromptSaver { |
392 | public: |
393 | PromptSaver() { |
394 | @@ -59,6 +62,7 @@ |
395 | int saved_point_; |
396 | char *saved_line_; |
397 | }; |
398 | +} |
399 | |
400 | namespace mcs { |
401 | namespace client { |
402 | @@ -434,9 +438,10 @@ |
403 | return; |
404 | } |
405 | |
406 | - // Use a high enough timeout to make sure we get the end of the scan |
407 | - // method call which has an internal timeout of 30 seconds |
408 | - g_dbus_proxy_set_default_timeout(G_DBUS_PROXY(inst->manager_), 60 * 1000); |
409 | + // Use a high enough timeout to make sure we wait enough for the service to |
410 | + // respond as the connection process can take some time depending on different |
411 | + // factors. |
412 | + g_dbus_proxy_set_default_timeout(G_DBUS_PROXY(inst->manager_), kDBusTimeout * 1000); |
413 | |
414 | aethercast_interface_object_manager_client_new(inst->bus_connection_, |
415 | G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, |
416 | |
417 | === added directory 'src/mcs/android' |
418 | === added file 'src/mcs/android/fileoutputtarget.cpp' |
419 | --- src/mcs/android/fileoutputtarget.cpp 1970-01-01 00:00:00 +0000 |
420 | +++ src/mcs/android/fileoutputtarget.cpp 2016-01-27 13:00:21 +0000 |
421 | @@ -0,0 +1,55 @@ |
422 | +/* |
423 | + * Copyright (C) 2016 Canonical, Ltd. |
424 | + * |
425 | + * This program is free software: you can redistribute it and/or modify it |
426 | + * under the terms of the GNU General Public License version 3, as published |
427 | + * by the Free Software Foundation. |
428 | + * |
429 | + * This program is distributed in the hope that it will be useful, but |
430 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
431 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
432 | + * PURPOSE. See the GNU General Public License for more details. |
433 | + * |
434 | + * You should have received a copy of the GNU General Public License along |
435 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
436 | + * |
437 | + */ |
438 | + |
439 | +#include <unistd.h> |
440 | +#include <sys/stat.h> |
441 | +#include <sys/types.h> |
442 | +#include <fcntl.h> |
443 | + |
444 | +#include "mcs/logger.h" |
445 | +#include "mcs/android/fileoutputtarget.h" |
446 | + |
447 | +namespace mcs { |
448 | +namespace android { |
449 | + |
450 | +FileOutputTarget::FileOutputTarget(const std::string &path, const H264Encoder::OutputFormat &format) : |
451 | + fd_(-1), |
452 | + format_(format) { |
453 | + |
454 | + ::unlink(path.c_str()); |
455 | + fd_ = ::open(path.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); |
456 | + if (fd_ < 0) { |
457 | + MCS_ERROR("Failed to create output file at path %s", path); |
458 | + return; |
459 | + } |
460 | +} |
461 | + |
462 | +FileOutputTarget::~FileOutputTarget() { |
463 | + if (fd_ > 0) |
464 | + close(fd_); |
465 | +} |
466 | + |
467 | +int FileOutputTarget::FileDescriptor() const { |
468 | + return fd_; |
469 | +} |
470 | + |
471 | +mcs::android::H264Encoder::OutputFormat FileOutputTarget::Format() const { |
472 | + return format_; |
473 | +} |
474 | + |
475 | +} // namespace android |
476 | +} // namespace mcs |
477 | |
478 | === added file 'src/mcs/android/fileoutputtarget.h' |
479 | --- src/mcs/android/fileoutputtarget.h 1970-01-01 00:00:00 +0000 |
480 | +++ src/mcs/android/fileoutputtarget.h 2016-01-27 13:00:21 +0000 |
481 | @@ -0,0 +1,42 @@ |
482 | +/* |
483 | + * Copyright (C) 2016 Canonical, Ltd. |
484 | + * |
485 | + * This program is free software: you can redistribute it and/or modify it |
486 | + * under the terms of the GNU General Public License version 3, as published |
487 | + * by the Free Software Foundation. |
488 | + * |
489 | + * This program is distributed in the hope that it will be useful, but |
490 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
491 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
492 | + * PURPOSE. See the GNU General Public License for more details. |
493 | + * |
494 | + * You should have received a copy of the GNU General Public License along |
495 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
496 | + * |
497 | + */ |
498 | + |
499 | +#ifndef MCS_ANDORID_FILEOUTPUTTARET_H_ |
500 | +#define MCS_ANDORID_FILEOUTPUTTARET_H_ |
501 | + |
502 | +#include <string> |
503 | + |
504 | +#include "mcs/android/h264encoder.h" |
505 | + |
506 | +namespace mcs { |
507 | +namespace android { |
508 | +class FileOutputTarget : public mcs::android::H264Encoder::OutputTarget { |
509 | +public: |
510 | + FileOutputTarget(const std::string &path, const mcs::android::H264Encoder::OutputFormat &format); |
511 | + ~FileOutputTarget(); |
512 | + |
513 | + int FileDescriptor() const override; |
514 | + mcs::android::H264Encoder::OutputFormat Format() const override; |
515 | + |
516 | +private: |
517 | + int fd_; |
518 | + mcs::android::H264Encoder::OutputFormat format_; |
519 | +}; |
520 | +} // namespace android |
521 | +} // namespace mcs |
522 | + |
523 | +#endif |
524 | |
525 | === added file 'src/mcs/android/h264encoder.cpp' |
526 | --- src/mcs/android/h264encoder.cpp 1970-01-01 00:00:00 +0000 |
527 | +++ src/mcs/android/h264encoder.cpp 2016-01-27 13:00:21 +0000 |
528 | @@ -0,0 +1,160 @@ |
529 | +/* |
530 | + * Copyright (C) 2016 Canonical, Ltd. |
531 | + * |
532 | + * This program is free software: you can redistribute it and/or modify it |
533 | + * under the terms of the GNU General Public License version 3, as published |
534 | + * by the Free Software Foundation. |
535 | + * |
536 | + * This program is distributed in the hope that it will be useful, but |
537 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
538 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
539 | + * PURPOSE. See the GNU General Public License for more details. |
540 | + * |
541 | + * You should have received a copy of the GNU General Public License along |
542 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
543 | + * |
544 | + */ |
545 | + |
546 | +#include <unistd.h> |
547 | + |
548 | +#include <hybris/media/media_recorder_layer.h> |
549 | + |
550 | +#include "mcs/logger.h" |
551 | +#include "mcs/utils.h" |
552 | +#include "mcs/android/h264encoder.h" |
553 | + |
554 | +namespace mcs { |
555 | +namespace android { |
556 | + |
557 | +H264Encoder::Ptr H264Encoder::Create(const OutputTarget &output) { |
558 | + return std::shared_ptr<H264Encoder>(new H264Encoder(output)); |
559 | +} |
560 | + |
561 | +H264Encoder::H264Encoder(const OutputTarget &output) : |
562 | + recorder_(nullptr), |
563 | + recorder_observer_(nullptr), |
564 | + recorder_source_(nullptr) { |
565 | + |
566 | + ::OutputFormat format = ANDROID_OUTPUT_FORMAT_DEFAULT; |
567 | + |
568 | + switch (output.Format()) { |
569 | + case OutputFormat::kMPEG2TS: |
570 | + format = ANDROID_OUTPUT_FORMAT_MPEG2TS; |
571 | + break; |
572 | + case OutputFormat::kMPEG4: |
573 | + format = ANDROID_OUTPUT_FORMAT_MPEG_4; |
574 | + break; |
575 | + case OutputFormat::kRTPAVP: |
576 | + format = ANDROID_OUTPUT_FORMAT_RTP_AVP; |
577 | + break; |
578 | + default: |
579 | + MCS_ERROR("Unsupported output format"); |
580 | + return; |
581 | + } |
582 | + |
583 | + // FIXME we need to instantiate an observer here as otherwise |
584 | + // the camera service can't find one and will crash. |
585 | + recorder_observer_ = android_media_recorder_observer_new(); |
586 | + if (!recorder_observer_) { |
587 | + MCS_ERROR("Failed to create recorder observer instance"); |
588 | + return; |
589 | + } |
590 | + |
591 | + // Also need to install a proper callback here for the observer |
592 | + // until it properly checks for a assigned callback internally. |
593 | + android_media_recorder_observer_set_cb(recorder_observer_, [](bool started, void *context) { |
594 | + (void) context; |
595 | + |
596 | + if (started) |
597 | + MCS_DEBUG("Recording started"); |
598 | + else |
599 | + MCS_DEBUG("Recording stopped"); |
600 | + }, nullptr); |
601 | + |
602 | + recorder_ = android_media_new_recorder(); |
603 | + if (!recorder_) { |
604 | + MCS_ERROR("Failed to create a recorder instance"); |
605 | + return; |
606 | + } |
607 | + |
608 | + // It's really important that we set the video source first as otherwise |
609 | + // the encoder doesn't enter the 'configured' state and all subsequent |
610 | + // calls will fail. |
611 | + android_recorder_setVideoSource(recorder_, ANDROID_VIDEO_SOURCE_GRALLOC_BUFFER); |
612 | + |
613 | + android_recorder_setOutputFormat(recorder_, format); |
614 | + android_recorder_setVideoEncoder(recorder_, ANDROID_VIDEO_ENCODER_H264); |
615 | + android_recorder_setOutputFile(recorder_, output.FileDescriptor()); |
616 | +} |
617 | + |
618 | +H264Encoder::~H264Encoder() { |
619 | + if (recorder_) |
620 | + android_recorder_release(recorder_); |
621 | + |
622 | + if (recorder_observer_) |
623 | + android_media_recorder_observer_release(recorder_observer_); |
624 | +} |
625 | + |
626 | +void* H264Encoder::NativeWindowHandle() const { |
627 | + if (!recorder_ && !recorder_source_) |
628 | + return nullptr; |
629 | + |
630 | + return android_recorder_source_get_native_handle(recorder_source_); |
631 | +} |
632 | + |
633 | +void H264Encoder::SetFramerate(unsigned int framerate) { |
634 | + if (!recorder_) |
635 | + return; |
636 | + |
637 | + android_recorder_setVideoFrameRate(recorder_, framerate); |
638 | +} |
639 | + |
640 | +void H264Encoder::SetBitrate(unsigned int bitrate) { |
641 | + if (!recorder_) |
642 | + return; |
643 | + |
644 | + auto param = mcs::Utils::Sprintf("video-param-encoding-bitrate=%d", bitrate); |
645 | + |
646 | + android_recorder_setParameters(recorder_, param.c_str()); |
647 | +} |
648 | + |
649 | +void H264Encoder::SetIFrameInterval(unsigned int interval) { |
650 | + if (!recorder_) |
651 | + return; |
652 | + |
653 | + auto param = mcs::Utils::Sprintf("video-param-i-frames-interval=%d", interval); |
654 | + |
655 | + android_recorder_setParameters(recorder_, param.c_str()); |
656 | +} |
657 | + |
658 | +void H264Encoder::SetDimensions(unsigned int width, unsigned int height) { |
659 | + if (!recorder_) |
660 | + return; |
661 | + |
662 | + android_recorder_setVideoSize(recorder_, width, height); |
663 | +} |
664 | + |
665 | +void H264Encoder::Start() { |
666 | + if (!recorder_) |
667 | + return; |
668 | + |
669 | + android_recorder_prepare(recorder_); |
670 | + android_recorder_start(recorder_); |
671 | + |
672 | + recorder_source_ = android_recorder_query_source(recorder_); |
673 | + if (!recorder_source_) { |
674 | + MCS_ERROR("Failed to query source from recorder instance"); |
675 | + return; |
676 | + } |
677 | +} |
678 | + |
679 | +void H264Encoder::Stop() { |
680 | + if (!recorder_) |
681 | + return; |
682 | + |
683 | + android_recorder_stop(recorder_); |
684 | + recorder_source_ = nullptr; |
685 | +} |
686 | + |
687 | +} // namespace android |
688 | +} // namespace mcs |
689 | |
690 | === added file 'src/mcs/android/h264encoder.h' |
691 | --- src/mcs/android/h264encoder.h 1970-01-01 00:00:00 +0000 |
692 | +++ src/mcs/android/h264encoder.h 2016-01-27 13:00:21 +0000 |
693 | @@ -0,0 +1,77 @@ |
694 | +/* |
695 | + * Copyright (C) 2016 Canonical, Ltd. |
696 | + * |
697 | + * This program is free software: you can redistribute it and/or modify it |
698 | + * under the terms of the GNU General Public License version 3, as published |
699 | + * by the Free Software Foundation. |
700 | + * |
701 | + * This program is distributed in the hope that it will be useful, but |
702 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
703 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
704 | + * PURPOSE. See the GNU General Public License for more details. |
705 | + * |
706 | + * You should have received a copy of the GNU General Public License along |
707 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
708 | + * |
709 | + */ |
710 | + |
711 | +#ifndef MCS_ANDORID_ENCODER_H_ |
712 | +#define MCS_ANDORID_ENCODER_H_ |
713 | + |
714 | +#include <memory> |
715 | + |
716 | +#include "mcs/non_copyable.h" |
717 | + |
718 | +struct MediaRecorderWrapper; |
719 | +struct MediaRecorderObserver; |
720 | +struct MediaRecorderSource; |
721 | + |
722 | +namespace mcs { |
723 | +namespace android { |
724 | +class H264Encoder { |
725 | +public: |
726 | + typedef std::shared_ptr<H264Encoder> Ptr; |
727 | + |
728 | + enum class OutputFormat { |
729 | + kRaw = 0, |
730 | + kMPEG4, |
731 | + kMPEG2TS, |
732 | + kRTPAVP |
733 | + }; |
734 | + |
735 | + class OutputTarget : public mcs::NonCopyable { |
736 | + public: |
737 | + // This will return a file descriptor the encoder can write its |
738 | + // data to. |
739 | + virtual int FileDescriptor() const = 0; |
740 | + |
741 | + // Describes the output format the encoder should use |
742 | + virtual OutputFormat Format() const = 0; |
743 | + }; |
744 | + |
745 | + static Ptr Create(const OutputTarget &output); |
746 | + |
747 | + ~H264Encoder(); |
748 | + |
749 | + void Start(); |
750 | + void Stop(); |
751 | + |
752 | + void* NativeWindowHandle() const; |
753 | + |
754 | + void SetFramerate(unsigned int framerate); |
755 | + void SetBitrate(unsigned int bitrate); |
756 | + void SetIFrameInterval(unsigned int interval); |
757 | + void SetDimensions(unsigned int width, unsigned int height); |
758 | + |
759 | +private: |
760 | + H264Encoder(const OutputTarget &output); |
761 | + |
762 | +private: |
763 | + MediaRecorderWrapper *recorder_; |
764 | + MediaRecorderObserver *recorder_observer_; |
765 | + MediaRecorderSource *recorder_source_; |
766 | +}; |
767 | +} // namespace android |
768 | +} // namespace mcs |
769 | + |
770 | +#endif |
771 | |
772 | === added file 'src/mcs/android/pipedoutputtarget.cpp' |
773 | --- src/mcs/android/pipedoutputtarget.cpp 1970-01-01 00:00:00 +0000 |
774 | +++ src/mcs/android/pipedoutputtarget.cpp 2016-01-27 13:00:21 +0000 |
775 | @@ -0,0 +1,54 @@ |
776 | +/* |
777 | + * Copyright (C) 2016 Canonical, Ltd. |
778 | + * |
779 | + * This program is free software: you can redistribute it and/or modify it |
780 | + * under the terms of the GNU General Public License version 3, as published |
781 | + * by the Free Software Foundation. |
782 | + * |
783 | + * This program is distributed in the hope that it will be useful, but |
784 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
785 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
786 | + * PURPOSE. See the GNU General Public License for more details. |
787 | + * |
788 | + * You should have received a copy of the GNU General Public License along |
789 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
790 | + * |
791 | + */ |
792 | + |
793 | +#include <unistd.h> |
794 | + |
795 | +#include "mcs/logger.h" |
796 | +#include "mcs/android/pipedoutputtarget.h" |
797 | + |
798 | +namespace mcs { |
799 | +namespace android { |
800 | + |
801 | +PipedOutputTarget::PipedOutputTarget(const H264Encoder::OutputFormat &format) : |
802 | + format_(format) { |
803 | + if (::pipe(fds_) < 0) { |
804 | + MCS_ERROR("Failed to create piped output target"); |
805 | + return; |
806 | + } |
807 | +} |
808 | + |
809 | +PipedOutputTarget::~PipedOutputTarget() { |
810 | + if (fds_[0] > 0) { |
811 | + close(fds_[0]); |
812 | + close(fds_[1]); |
813 | + } |
814 | +} |
815 | + |
816 | +int PipedOutputTarget::FileDescriptor() const { |
817 | + return fds_[1]; |
818 | +} |
819 | + |
820 | +mcs::android::H264Encoder::OutputFormat PipedOutputTarget::Format() const { |
821 | + return format_; |
822 | +} |
823 | + |
824 | +int PipedOutputTarget::OutputFileDescriptor() const { |
825 | + return fds_[0]; |
826 | +} |
827 | + |
828 | +} // namespace android |
829 | +} // namespace mcs |
830 | |
831 | === added file 'src/mcs/android/pipedoutputtarget.h' |
832 | --- src/mcs/android/pipedoutputtarget.h 1970-01-01 00:00:00 +0000 |
833 | +++ src/mcs/android/pipedoutputtarget.h 2016-01-27 13:00:21 +0000 |
834 | @@ -0,0 +1,42 @@ |
835 | +/* |
836 | + * Copyright (C) 2016 Canonical, Ltd. |
837 | + * |
838 | + * This program is free software: you can redistribute it and/or modify it |
839 | + * under the terms of the GNU General Public License version 3, as published |
840 | + * by the Free Software Foundation. |
841 | + * |
842 | + * This program is distributed in the hope that it will be useful, but |
843 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
844 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
845 | + * PURPOSE. See the GNU General Public License for more details. |
846 | + * |
847 | + * You should have received a copy of the GNU General Public License along |
848 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
849 | + * |
850 | + */ |
851 | + |
852 | +#ifndef MCS_ANDORID_PIPEDOUTPUTTARET_H_ |
853 | +#define MCS_ANDORID_PIPEDOUTPUTTARET_H_ |
854 | + |
855 | +#include "mcs/android/h264encoder.h" |
856 | + |
857 | +namespace mcs { |
858 | +namespace android { |
859 | +class PipedOutputTarget : public mcs::android::H264Encoder::OutputTarget { |
860 | +public: |
861 | + PipedOutputTarget(const mcs::android::H264Encoder::OutputFormat &format); |
862 | + ~PipedOutputTarget(); |
863 | + |
864 | + int FileDescriptor() const override; |
865 | + mcs::android::H264Encoder::OutputFormat Format() const override; |
866 | + |
867 | + int OutputFileDescriptor() const; |
868 | + |
869 | +private: |
870 | + int fds_[2]; |
871 | + mcs::android::H264Encoder::OutputFormat format_; |
872 | +}; |
873 | +} // namespace android |
874 | +} // namespace mcs |
875 | + |
876 | +#endif |
877 | |
878 | === modified file 'src/mcs/basesourcemediamanager.cpp' |
879 | --- src/mcs/basesourcemediamanager.cpp 2015-12-07 16:02:43 +0000 |
880 | +++ src/mcs/basesourcemediamanager.cpp 2016-01-27 13:00:21 +0000 |
881 | @@ -15,9 +15,12 @@ |
882 | * |
883 | */ |
884 | |
885 | +#include <iostream> |
886 | + |
887 | #include <glib.h> |
888 | |
889 | #include "basesourcemediamanager.h" |
890 | +#include "videoformat.h" |
891 | #include "logger.h" |
892 | |
893 | namespace mcs { |
894 | @@ -38,24 +41,23 @@ |
895 | return sink_port1_; |
896 | } |
897 | |
898 | -std::vector<wds::H264VideoCodec> GetH264VideoCodecs() { |
899 | +std::vector<wds::H264VideoCodec> BaseSourceMediaManager::GetH264VideoCodecs() { |
900 | static std::vector<wds::H264VideoCodec> codecs; |
901 | if (codecs.empty()) { |
902 | wds::RateAndResolutionsBitmap cea_rr; |
903 | wds::RateAndResolutionsBitmap vesa_rr; |
904 | wds::RateAndResolutionsBitmap hh_rr; |
905 | wds::RateAndResolution i; |
906 | - // declare that we support all resolutions, CHP and level 4.2 |
907 | - // gstreamer should handle all of it :) |
908 | + |
909 | for (i = wds::CEA640x480p60; i <= wds::CEA1920x1080p24; ++i) |
910 | cea_rr.set(i); |
911 | - for (i = wds::VESA800x600p30; i <= wds::VESA1920x1200p30; ++i) |
912 | - vesa_rr.set(i); |
913 | - for (i = wds::HH800x480p30; i <= wds::HH848x480p60; ++i) |
914 | - hh_rr.set(i); |
915 | |
916 | - wds::H264VideoCodec codec(wds::CHP, wds::k4_2, cea_rr, vesa_rr, hh_rr); |
917 | + wds::H264VideoCodec codec(wds::CHP, wds::k4, cea_rr, vesa_rr, hh_rr); |
918 | codecs.push_back(codec); |
919 | + |
920 | + DEBUG("Video codecs supported by us:"); |
921 | + for (auto c : codecs) |
922 | + mcs::video::DumpVideoCodec(c); |
923 | } |
924 | |
925 | return codecs; |
926 | @@ -64,15 +66,20 @@ |
927 | bool BaseSourceMediaManager::InitOptimalVideoFormat(const wds::NativeVideoFormat& sink_native_format, |
928 | const std::vector<wds::H264VideoCodec>& sink_supported_codecs) { |
929 | |
930 | + DEBUG("Sink native resolution:"); |
931 | + mcs::video::DumpNativeFormat(sink_native_format); |
932 | + |
933 | + DEBUG("Sink supports the following codecs:"); |
934 | + for (auto sink_codec : sink_supported_codecs) { |
935 | + mcs::video::DumpVideoCodec(sink_codec); |
936 | + } |
937 | + |
938 | format_ = wds::FindOptimalVideoFormat(sink_native_format, |
939 | GetH264VideoCodecs(), |
940 | sink_supported_codecs); |
941 | |
942 | - INFO("Found optimal video format"); |
943 | - INFO(" profile: %d", format_.profile); |
944 | - INFO(" level: %d", format_.level); |
945 | - INFO(" res type %d", format_.type); |
946 | - INFO(" rate & resolution %d", format_.rate_resolution); |
947 | + DEBUG("Found optimal video format:"); |
948 | + mcs::video::DumpVideoFormat(format_); |
949 | |
950 | Configure(); |
951 | |
952 | |
953 | === modified file 'src/mcs/basesourcemediamanager.h' |
954 | --- src/mcs/basesourcemediamanager.h 2015-11-26 16:48:53 +0000 |
955 | +++ src/mcs/basesourcemediamanager.h 2016-01-27 13:00:21 +0000 |
956 | @@ -38,6 +38,7 @@ |
957 | |
958 | protected: |
959 | virtual void Configure() = 0; |
960 | + virtual std::vector<wds::H264VideoCodec> GetH264VideoCodecs(); |
961 | |
962 | protected: |
963 | int sink_port1_; |
964 | |
965 | === renamed file 'src/w11t/command.cpp' => 'src/mcs/config.h.in' |
966 | --- src/w11t/command.cpp 2015-12-18 17:15:31 +0000 |
967 | +++ src/mcs/config.h.in 2016-01-27 13:00:21 +0000 |
968 | @@ -15,11 +15,11 @@ |
969 | * |
970 | */ |
971 | |
972 | -#include "command.h" |
973 | - |
974 | -namespace w11t { |
975 | -Command::Command(const Message &message, ResponseCallback callback) : |
976 | - message(message), |
977 | - callback(callback) { |
978 | -} |
979 | -} |
980 | +#ifndef MCS_CONFIG_H_ |
981 | +#define MCS_CONFIG_H_ |
982 | + |
983 | +namespace mcs { |
984 | +constexpr const char* kRuntimePath{"/run/aethercast"}; |
985 | +} |
986 | + |
987 | +#endif |
988 | |
989 | === modified file 'src/mcs/dbushelpers.cpp' |
990 | --- src/mcs/dbushelpers.cpp 2015-12-07 15:40:38 +0000 |
991 | +++ src/mcs/dbushelpers.cpp 2016-01-27 13:00:21 +0000 |
992 | @@ -19,15 +19,58 @@ |
993 | |
994 | namespace mcs { |
995 | |
996 | -gchar** DBusHelpers::GenerateCapabilities(const std::vector<NetworkDeviceRole> roles) { |
997 | - gchar** capabilities = g_new0(gchar*, roles.size() + 1); |
998 | +gchar** DBusHelpers::GenerateDeviceCapabilities(const std::vector<NetworkDeviceRole> &roles) { |
999 | + gchar **capabilities = g_new0(gchar*, roles.size() + 1); |
1000 | int n = 0; |
1001 | for (auto role : roles) |
1002 | - capabilities[n] = g_strdup(NetworkDevice::RoleToStr(roles[n++]).c_str()); |
1003 | + capabilities[n] = g_strdup(NetworkDevice::RoleToStr(role).c_str()); |
1004 | capabilities[n] = nullptr; |
1005 | return capabilities; |
1006 | } |
1007 | |
1008 | +gchar** DBusHelpers::GenerateCapabilities(const std::vector<NetworkManager::Capability> &capabilities) { |
1009 | + gchar** out_capabilities = g_new0(gchar*, capabilities.size() + 1); |
1010 | + int n = 0; |
1011 | + for (auto capability : capabilities) { |
1012 | + auto value = NetworkManager::CapabilityToStr(capability); |
1013 | + out_capabilities[n++] = g_strdup(value.c_str()); |
1014 | + } |
1015 | + out_capabilities[n] = nullptr; |
1016 | + return out_capabilities; |
1017 | +} |
1018 | + |
1019 | +void DBusHelpers::ParseDictionary(GVariant *properties, std::function<void(std::string, GVariant*)> callback, const std::string &key_filter) { |
1020 | + if (!callback || !properties) |
1021 | + return; |
1022 | + |
1023 | + for (int n = 0; n < g_variant_n_children(properties); n++) { |
1024 | + auto property = g_variant_get_child_value(properties, n); |
1025 | + auto key_v = g_variant_get_child_value(property, 0); |
1026 | + auto value_v = g_variant_get_child_value(property, 1); |
1027 | + |
1028 | + std::string key = g_variant_get_string(key_v, nullptr); |
1029 | + |
1030 | + if (key_filter.length() > 0) { |
1031 | + if (key_filter != key) |
1032 | + continue; |
1033 | + |
1034 | + callback(key, value_v); |
1035 | + } |
1036 | + else |
1037 | + callback(key, value_v); |
1038 | + } |
1039 | +} |
1040 | + |
1041 | +void DBusHelpers::ParseArray(GVariant *array, std::function<void(GVariant*)> callback) { |
1042 | + if (!callback || !array) |
1043 | + return; |
1044 | + |
1045 | + for (int n = 0; n < g_variant_n_children(array); n++) { |
1046 | + auto element = g_variant_get_child_value(array, n); |
1047 | + callback(element); |
1048 | + } |
1049 | +} |
1050 | + |
1051 | } // namespace mcs |
1052 | |
1053 | |
1054 | |
1055 | === modified file 'src/mcs/dbushelpers.h' |
1056 | --- src/mcs/dbushelpers.h 2015-12-07 15:40:38 +0000 |
1057 | +++ src/mcs/dbushelpers.h 2016-01-27 13:00:21 +0000 |
1058 | @@ -18,14 +18,21 @@ |
1059 | #ifndef DBUSHELPERS_H_ |
1060 | #define DBUSHELPERS_H_ |
1061 | |
1062 | +#include <functional> |
1063 | + |
1064 | #include <glib.h> |
1065 | +#include <gio/gio.h> |
1066 | |
1067 | -#include "networkdevice.h" |
1068 | +#include "networkmanager.h" |
1069 | +#include "scoped_gobject.h" |
1070 | |
1071 | namespace mcs { |
1072 | |
1073 | struct DBusHelpers { |
1074 | - static gchar** GenerateCapabilities(const std::vector<NetworkDeviceRole> roles); |
1075 | + static gchar** GenerateCapabilities(const std::vector<NetworkManager::Capability> &capabilities); |
1076 | + static gchar** GenerateDeviceCapabilities(const std::vector<NetworkDeviceRole> &roles); |
1077 | + static void ParseDictionary(GVariant *properties, std::function<void(std::string, GVariant*)> callback, const std::string &key_filter = ""); |
1078 | + static void ParseArray(GVariant *array, std::function<void(GVariant*)> callback); |
1079 | }; |
1080 | |
1081 | } // namespace mcs |
1082 | |
1083 | === modified file 'src/mcs/forwardingmiracastcontroller.cpp' |
1084 | --- src/mcs/forwardingmiracastcontroller.cpp 2015-12-11 22:02:52 +0000 |
1085 | +++ src/mcs/forwardingmiracastcontroller.cpp 2016-01-27 13:00:21 +0000 |
1086 | @@ -50,8 +50,8 @@ |
1087 | return fwd_->State(); |
1088 | } |
1089 | |
1090 | -std::vector<NetworkDeviceRole> ForwardingMiracastController::SupportedRoles() const { |
1091 | - return fwd_->SupportedRoles(); |
1092 | +std::vector<NetworkManager::Capability> ForwardingMiracastController::Capabilities() const { |
1093 | + return fwd_->Capabilities(); |
1094 | } |
1095 | |
1096 | bool ForwardingMiracastController::Scanning() const { |
1097 | |
1098 | === modified file 'src/mcs/forwardingmiracastcontroller.h' |
1099 | --- src/mcs/forwardingmiracastcontroller.h 2015-12-11 22:02:52 +0000 |
1100 | +++ src/mcs/forwardingmiracastcontroller.h 2016-01-27 13:00:21 +0000 |
1101 | @@ -35,7 +35,7 @@ |
1102 | virtual void Scan(const std::chrono::seconds &timeout = std::chrono::seconds{30}) override; |
1103 | |
1104 | virtual NetworkDeviceState State() const override; |
1105 | - virtual std::vector<NetworkDeviceRole> SupportedRoles() const override; |
1106 | + virtual std::vector<NetworkManager::Capability> Capabilities() const override; |
1107 | virtual bool Scanning() const override; |
1108 | |
1109 | private: |
1110 | |
1111 | === added file 'src/mcs/forwardingnetworkdevice.cpp' |
1112 | --- src/mcs/forwardingnetworkdevice.cpp 1970-01-01 00:00:00 +0000 |
1113 | +++ src/mcs/forwardingnetworkdevice.cpp 2016-01-27 13:00:21 +0000 |
1114 | @@ -0,0 +1,51 @@ |
1115 | +/* |
1116 | +* Copyright (C) 2015 Canonical, Ltd. |
1117 | +* |
1118 | +* This program is free software: you can redistribute it and/or modify it |
1119 | +* under the terms of the GNU General Public License version 3, as published |
1120 | +* by the Free Software Foundation. |
1121 | +* |
1122 | +* This program is distributed in the hope that it will be useful, but |
1123 | +* WITHOUT ANY WARRANTY; without even the implied warranties of |
1124 | +* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1125 | +* PURPOSE. See the GNU General Public License for more details. |
1126 | +* |
1127 | +* You should have received a copy of the GNU General Public License along |
1128 | +* with this program. If not, see <http://www.gnu.org/licenses/>. |
1129 | +* |
1130 | +*/ |
1131 | + |
1132 | +#include "forwardingnetworkdevice.h" |
1133 | + |
1134 | +namespace mcs { |
1135 | + |
1136 | +ForwardingNetworkDevice::ForwardingNetworkDevice(const NetworkDevice::Ptr& fwd) : fwd_(fwd) { |
1137 | + if (not fwd_) { |
1138 | + throw std::logic_error{"Cannot operate without a valid NetworkDevice instance."}; |
1139 | + } |
1140 | +} |
1141 | + |
1142 | +MacAddress ForwardingNetworkDevice::Address() const { |
1143 | + return fwd_->Address(); |
1144 | +} |
1145 | + |
1146 | +IpV4Address ForwardingNetworkDevice::IPv4Address() const { |
1147 | + return fwd_->IPv4Address(); |
1148 | +} |
1149 | + |
1150 | +std::string ForwardingNetworkDevice::Name() const { |
1151 | + return fwd_->Name(); |
1152 | +} |
1153 | + |
1154 | +NetworkDeviceState ForwardingNetworkDevice::State() const { |
1155 | + return fwd_->State(); |
1156 | +} |
1157 | + |
1158 | +std::vector<NetworkDeviceRole> ForwardingNetworkDevice::SupportedRoles() const { |
1159 | + return fwd_->SupportedRoles(); |
1160 | +} |
1161 | + |
1162 | +const NetworkDevice::Ptr& ForwardingNetworkDevice::Fwd() const { |
1163 | + return fwd_; |
1164 | +} |
1165 | +} // namespace mcs |
1166 | |
1167 | === removed file 'src/mcs/forwardingnetworkdevice.cpp' |
1168 | --- src/mcs/forwardingnetworkdevice.cpp 2015-12-16 08:04:35 +0000 |
1169 | +++ src/mcs/forwardingnetworkdevice.cpp 1970-01-01 00:00:00 +0000 |
1170 | @@ -1,51 +0,0 @@ |
1171 | -/* |
1172 | -* Copyright (C) 2015 Canonical, Ltd. |
1173 | -* |
1174 | -* This program is free software: you can redistribute it and/or modify it |
1175 | -* under the terms of the GNU General Public License version 3, as published |
1176 | -* by the Free Software Foundation. |
1177 | -* |
1178 | -* This program is distributed in the hope that it will be useful, but |
1179 | -* WITHOUT ANY WARRANTY; without even the implied warranties of |
1180 | -* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1181 | -* PURPOSE. See the GNU General Public License for more details. |
1182 | -* |
1183 | -* You should have received a copy of the GNU General Public License along |
1184 | -* with this program. If not, see <http://www.gnu.org/licenses/>. |
1185 | -* |
1186 | -*/ |
1187 | - |
1188 | -#include "forwardingnetworkdevice.h" |
1189 | - |
1190 | -namespace mcs { |
1191 | - |
1192 | -ForwardingNetworkDevice::ForwardingNetworkDevice(const NetworkDevice::Ptr& fwd) : fwd_(fwd) { |
1193 | - if (not fwd_) { |
1194 | - throw std::logic_error{"Cannot operate without a valid NetworkDevice instance."}; |
1195 | - } |
1196 | -} |
1197 | - |
1198 | -MacAddress ForwardingNetworkDevice::Address() const { |
1199 | - return fwd_->Address(); |
1200 | -} |
1201 | - |
1202 | -IpV4Address ForwardingNetworkDevice::IPv4Address() const { |
1203 | - return fwd_->IPv4Address(); |
1204 | -} |
1205 | - |
1206 | -std::string ForwardingNetworkDevice::Name() const { |
1207 | - return fwd_->Name(); |
1208 | -} |
1209 | - |
1210 | -NetworkDeviceState ForwardingNetworkDevice::State() const { |
1211 | - return fwd_->State(); |
1212 | -} |
1213 | - |
1214 | -std::vector<NetworkDeviceRole> ForwardingNetworkDevice::SupportedRoles() const { |
1215 | - return fwd_->SupportedRoles(); |
1216 | -} |
1217 | - |
1218 | -const NetworkDevice::Ptr& ForwardingNetworkDevice::Fwd() const { |
1219 | - return fwd_; |
1220 | -} |
1221 | -} // namespace mcs |
1222 | |
1223 | === added file 'src/mcs/forwardingnetworkdevice.h' |
1224 | --- src/mcs/forwardingnetworkdevice.h 1970-01-01 00:00:00 +0000 |
1225 | +++ src/mcs/forwardingnetworkdevice.h 2016-01-27 13:00:21 +0000 |
1226 | @@ -0,0 +1,42 @@ |
1227 | +/* |
1228 | +* Copyright (C) 2015 Canonical, Ltd. |
1229 | +* |
1230 | +* This program is free software: you can redistribute it and/or modify it |
1231 | +* under the terms of the GNU General Public License version 3, as published |
1232 | +* by the Free Software Foundation. |
1233 | +* |
1234 | +* This program is distributed in the hope that it will be useful, but |
1235 | +* WITHOUT ANY WARRANTY; without even the implied warranties of |
1236 | +* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1237 | +* PURPOSE. See the GNU General Public License for more details. |
1238 | +* |
1239 | +* You should have received a copy of the GNU General Public License along |
1240 | +* with this program. If not, see <http://www.gnu.org/licenses/>. |
1241 | +* |
1242 | +*/ |
1243 | + |
1244 | +#ifndef FORWARDINGNETWORKDEVICE_H_ |
1245 | +#define FORWARDINGNETWORKDEVICE_H_ |
1246 | + |
1247 | +#include "networkdevice.h" |
1248 | + |
1249 | +namespace mcs { |
1250 | + |
1251 | +class ForwardingNetworkDevice : public NetworkDevice { |
1252 | +public: |
1253 | + ForwardingNetworkDevice(const NetworkDevice::Ptr& fwd); |
1254 | + |
1255 | + MacAddress Address() const override; |
1256 | + IpV4Address IPv4Address() const override; |
1257 | + std::string Name() const override; |
1258 | + NetworkDeviceState State() const override; |
1259 | + std::vector<NetworkDeviceRole> SupportedRoles() const override; |
1260 | + |
1261 | +protected: |
1262 | + const NetworkDevice::Ptr& Fwd() const; |
1263 | + |
1264 | +private: |
1265 | + NetworkDevice::Ptr fwd_; |
1266 | +}; |
1267 | +} // namespace mcs |
1268 | +#endif |
1269 | |
1270 | === removed file 'src/mcs/forwardingnetworkdevice.h' |
1271 | --- src/mcs/forwardingnetworkdevice.h 2015-12-16 08:04:35 +0000 |
1272 | +++ src/mcs/forwardingnetworkdevice.h 1970-01-01 00:00:00 +0000 |
1273 | @@ -1,42 +0,0 @@ |
1274 | -/* |
1275 | -* Copyright (C) 2015 Canonical, Ltd. |
1276 | -* |
1277 | -* This program is free software: you can redistribute it and/or modify it |
1278 | -* under the terms of the GNU General Public License version 3, as published |
1279 | -* by the Free Software Foundation. |
1280 | -* |
1281 | -* This program is distributed in the hope that it will be useful, but |
1282 | -* WITHOUT ANY WARRANTY; without even the implied warranties of |
1283 | -* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1284 | -* PURPOSE. See the GNU General Public License for more details. |
1285 | -* |
1286 | -* You should have received a copy of the GNU General Public License along |
1287 | -* with this program. If not, see <http://www.gnu.org/licenses/>. |
1288 | -* |
1289 | -*/ |
1290 | - |
1291 | -#ifndef FORWARDINGNETWORKDEVICE_H_ |
1292 | -#define FORWARDINGNETWORKDEVICE_H_ |
1293 | - |
1294 | -#include "networkdevice.h" |
1295 | - |
1296 | -namespace mcs { |
1297 | - |
1298 | -class ForwardingNetworkDevice : public NetworkDevice { |
1299 | -public: |
1300 | - ForwardingNetworkDevice(const NetworkDevice::Ptr& fwd); |
1301 | - |
1302 | - MacAddress Address() const override; |
1303 | - IpV4Address IPv4Address() const override; |
1304 | - std::string Name() const override; |
1305 | - NetworkDeviceState State() const override; |
1306 | - std::vector<NetworkDeviceRole> SupportedRoles() const override; |
1307 | - |
1308 | -protected: |
1309 | - const NetworkDevice::Ptr& Fwd() const; |
1310 | - |
1311 | -private: |
1312 | - NetworkDevice::Ptr fwd_; |
1313 | -}; |
1314 | -} // namespace mcs |
1315 | -#endif |
1316 | |
1317 | === modified file 'src/mcs/gobject_deleter.h' |
1318 | --- src/mcs/gobject_deleter.h 2015-11-30 10:41:56 +0000 |
1319 | +++ src/mcs/gobject_deleter.h 2016-01-27 13:00:21 +0000 |
1320 | @@ -19,6 +19,8 @@ |
1321 | |
1322 | #include <glib-object.h> |
1323 | |
1324 | +#include <mcs/logger.h> |
1325 | + |
1326 | namespace mcs { |
1327 | // A GObjectDeleter considers T to be a GObject and |
1328 | // provides an operator() that decrements the reference |
1329 | |
1330 | === modified file 'src/mcs/gstsourcemediamanager.cpp' |
1331 | --- src/mcs/gstsourcemediamanager.cpp 2015-12-09 16:07:13 +0000 |
1332 | +++ src/mcs/gstsourcemediamanager.cpp 2016-01-27 13:00:21 +0000 |
1333 | @@ -60,7 +60,7 @@ |
1334 | g_free (debug); |
1335 | break; |
1336 | default: |
1337 | - /* unhandled message */ |
1338 | + DEBUG(""); |
1339 | break; |
1340 | } |
1341 | |
1342 | @@ -68,6 +68,8 @@ |
1343 | } |
1344 | |
1345 | void GstSourceMediaManager::Configure() { |
1346 | + DEBUG(""); |
1347 | + |
1348 | pipeline_ = ConstructPipeline(format_); |
1349 | |
1350 | ScopedGObject<GstBus> bus{gst_pipeline_get_bus (GST_PIPELINE(pipeline_.get()))}; |
1351 | @@ -81,6 +83,8 @@ |
1352 | if (!pipeline_) |
1353 | return; |
1354 | |
1355 | + DEBUG(""); |
1356 | + |
1357 | gst_element_set_state(pipeline_.get(), GST_STATE_PLAYING); |
1358 | } |
1359 | |
1360 | @@ -88,6 +92,8 @@ |
1361 | if (!pipeline_) |
1362 | return; |
1363 | |
1364 | + DEBUG(""); |
1365 | + |
1366 | gst_element_set_state(pipeline_.get(), GST_STATE_PAUSED); |
1367 | } |
1368 | |
1369 | @@ -95,6 +101,8 @@ |
1370 | if (!pipeline_) |
1371 | return; |
1372 | |
1373 | + DEBUG(""); |
1374 | + |
1375 | gst_element_set_state(pipeline_.get(), GST_STATE_READY); |
1376 | } |
1377 | |
1378 | @@ -102,6 +110,8 @@ |
1379 | if (!pipeline_) |
1380 | return true; |
1381 | |
1382 | + DEBUG(""); |
1383 | + |
1384 | GstState state; |
1385 | gst_element_get_state(pipeline_.get(), &state, nullptr, GST_CLOCK_TIME_NONE); |
1386 | |
1387 | |
1388 | === added file 'src/mcs/initgstreameronce.cpp' |
1389 | --- src/mcs/initgstreameronce.cpp 1970-01-01 00:00:00 +0000 |
1390 | +++ src/mcs/initgstreameronce.cpp 2016-01-27 13:00:21 +0000 |
1391 | @@ -0,0 +1,88 @@ |
1392 | +/* |
1393 | + * Copyright (C) 2015 Canonical, Ltd. |
1394 | + * |
1395 | + * This program is free software: you can redistribute it and/or modify it |
1396 | + * under the terms of the GNU General Public License version 3, as published |
1397 | + * by the Free Software Foundation. |
1398 | + * |
1399 | + * This program is distributed in the hope that it will be useful, but |
1400 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1401 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1402 | + * PURPOSE. See the GNU General Public License for more details. |
1403 | + * |
1404 | + * You should have received a copy of the GNU General Public License along |
1405 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1406 | + * |
1407 | + */ |
1408 | + |
1409 | +#include <atomic> |
1410 | + |
1411 | +#include <gst/gst.h> |
1412 | + |
1413 | +#include "initgstreameronce.h" |
1414 | +#include "logger.h" |
1415 | + |
1416 | +namespace { |
1417 | +void GstLog (GstDebugCategory *category, |
1418 | + GstDebugLevel level, |
1419 | + const gchar *file, |
1420 | + const gchar *function, |
1421 | + gint line, |
1422 | + GObject *object, |
1423 | + GstDebugMessage *message, |
1424 | + gpointer user_data) { |
1425 | + |
1426 | + boost::optional<mcs::Logger::Location> location; |
1427 | + if (file && function && line > 0) { |
1428 | + location = mcs::Logger::Location{file, function, line}; |
1429 | + } |
1430 | + |
1431 | + mcs::Log().Log(mcs::GstDebugLevelToSeverity(level), gst_debug_message_get(message), location); |
1432 | +} |
1433 | +} |
1434 | +namespace mcs { |
1435 | +Logger::Severity GstDebugLevelToSeverity(GstDebugLevel level) { |
1436 | + switch (level) { |
1437 | + case GST_LEVEL_NONE: |
1438 | + case GST_LEVEL_ERROR: |
1439 | + return Logger::Severity::kError; |
1440 | + case GST_LEVEL_WARNING: |
1441 | + case GST_LEVEL_FIXME: |
1442 | + return Logger::Severity::kWarning; |
1443 | + case GST_LEVEL_INFO: |
1444 | + return Logger::Severity::kInfo; |
1445 | + case GST_LEVEL_DEBUG: |
1446 | + return Logger::Severity::kDebug; |
1447 | + case GST_LEVEL_LOG: |
1448 | + return Logger::Severity::kDebug; |
1449 | + case GST_LEVEL_TRACE: |
1450 | + case GST_LEVEL_MEMDUMP: |
1451 | + return Logger::Severity::kTrace; |
1452 | + default: |
1453 | + return Logger::Severity::kInfo; |
1454 | + } |
1455 | +} |
1456 | + |
1457 | +void InitGstreamerOnceOrThrow() { |
1458 | + static std::atomic<bool> initialized(false); |
1459 | + if (initialized.exchange(true)) |
1460 | + return; |
1461 | + |
1462 | + GError* error = nullptr; |
1463 | + if (gst_init_check(nullptr, nullptr, &error) == FALSE) { |
1464 | + auto what = Utils::Sprintf("Failed to initialize gstreamer (%s: %s)", g_quark_to_string(error->domain), error->message); |
1465 | + g_error_free(error); |
1466 | + throw std::runtime_error{what}; |
1467 | + } |
1468 | + |
1469 | + // Get rid of gstreamer's default log function. |
1470 | + gst_debug_remove_log_function(nullptr); |
1471 | + // And install our own. |
1472 | + gst_debug_add_log_function(GstLog, nullptr, nullptr); |
1473 | + // No need to, our logging infra takes care of that, too. |
1474 | + gst_debug_set_colored(FALSE); |
1475 | + auto gst_debug = Utils::GetEnvValue("AETHERCAST_GST_DEBUG"); |
1476 | + if (not gst_debug.empty()) |
1477 | + gst_debug_set_threshold_from_string(gst_debug.c_str(), FALSE); |
1478 | +} |
1479 | +} |
1480 | |
1481 | === added file 'src/mcs/initgstreameronce.h' |
1482 | --- src/mcs/initgstreameronce.h 1970-01-01 00:00:00 +0000 |
1483 | +++ src/mcs/initgstreameronce.h 2016-01-27 13:00:21 +0000 |
1484 | @@ -0,0 +1,29 @@ |
1485 | +/* |
1486 | + * Copyright (C) 2015 Canonical, Ltd. |
1487 | + * |
1488 | + * This program is free software: you can redistribute it and/or modify it |
1489 | + * under the terms of the GNU General Public License version 3, as published |
1490 | + * by the Free Software Foundation. |
1491 | + * |
1492 | + * This program is distributed in the hope that it will be useful, but |
1493 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1494 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1495 | + * PURPOSE. See the GNU General Public License for more details. |
1496 | + * |
1497 | + * You should have received a copy of the GNU General Public License along |
1498 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1499 | + * |
1500 | + */ |
1501 | + |
1502 | +#include <gst/gst.h> |
1503 | + |
1504 | +#include "logger.h" |
1505 | + |
1506 | +namespace mcs { |
1507 | +// GstDebugLevelToSeverity maps a GstDebugLevel to a Logger::Severity; |
1508 | +Logger::Severity GstDebugLevelToSeverity(GstDebugLevel); |
1509 | + |
1510 | +// InitGstreamerOnceOrThrow initializes GStreamer, redirecting |
1511 | +// its debug output to the mcs::Logger facilities. |
1512 | +void InitGstreamerOnceOrThrow(); |
1513 | +} |
1514 | |
1515 | === modified file 'src/mcs/mediamanagerfactory.cpp' |
1516 | --- src/mcs/mediamanagerfactory.cpp 2015-12-07 16:02:43 +0000 |
1517 | +++ src/mcs/mediamanagerfactory.cpp 2016-01-27 13:00:21 +0000 |
1518 | @@ -19,7 +19,8 @@ |
1519 | |
1520 | #include "logger.h" |
1521 | #include "mediamanagerfactory.h" |
1522 | -#include "mirsourcemediamanager.h" |
1523 | +#include "mir/sourcemediamanager.h" |
1524 | +#include "x11sourcemediamanager.h" |
1525 | #include "testsourcemediamanager.h" |
1526 | #include "utils.h" |
1527 | #include "logging.h" |
1528 | @@ -49,10 +50,12 @@ |
1529 | std::shared_ptr<BaseSourceMediaManager> MediaManagerFactory::CreateSource(const std::string &remote_address) { |
1530 | std::string type = Utils::GetEnvValue("MIRACAST_SOURCE_TYPE"); |
1531 | |
1532 | - WARNING("Creating source media manager of type %s", type.c_str()); |
1533 | + DEBUG("Creating source media manager of type %s", type.c_str()); |
1534 | |
1535 | if (type.length() == 0 || type == "mir") |
1536 | - return std::make_shared<MirSourceMediaManager>(remote_address); |
1537 | + return std::make_shared<mcs::mir::SourceMediaManager>(remote_address); |
1538 | + else if (type == "x11") |
1539 | + return X11SourceMediaManager::create(remote_address); |
1540 | else if (type == "test") |
1541 | return TestSourceMediaManager::create(remote_address); |
1542 | |
1543 | |
1544 | === added directory 'src/mcs/mir' |
1545 | === renamed file 'src/mcs/mirsourcemediamanager.cpp' => 'src/mcs/mir/sourcemediamanager.cpp' |
1546 | --- src/mcs/mirsourcemediamanager.cpp 2015-12-07 16:02:43 +0000 |
1547 | +++ src/mcs/mir/sourcemediamanager.cpp 2016-01-27 13:00:21 +0000 |
1548 | @@ -15,99 +15,48 @@ |
1549 | * |
1550 | */ |
1551 | |
1552 | +#include <cassert> |
1553 | #include <sstream> |
1554 | |
1555 | -#include "mirsourcemediamanager.h" |
1556 | -#include "utils.h" |
1557 | -#include "logger.h" |
1558 | +#include "mcs/utils.h" |
1559 | +#include "mcs/logger.h" |
1560 | + |
1561 | +#include "mcs/videoformat.h" |
1562 | + |
1563 | +#include "mcs/mir/sourcemediamanager.h" |
1564 | |
1565 | namespace mcs { |
1566 | -MirSourceMediaManager::MirSourceMediaManager(const std::string &remote_address) : |
1567 | - remote_address_(remote_address) { |
1568 | -} |
1569 | - |
1570 | -MirSourceMediaManager::~MirSourceMediaManager() { |
1571 | -} |
1572 | - |
1573 | -SharedGObject<GstElement> MirSourceMediaManager::ConstructPipeline(const wds::H264VideoFormat &format) { |
1574 | - int width = 0, height = 0; |
1575 | - std::string profile = "constrained-baseline"; |
1576 | - |
1577 | - switch (format.profile) { |
1578 | - case wds::CBP: |
1579 | - profile = "constrained-baseline"; |
1580 | - break; |
1581 | - case wds::CHP: |
1582 | - profile = "high"; |
1583 | - break; |
1584 | - } |
1585 | - |
1586 | - switch (format.type) { |
1587 | - case wds::CEA: |
1588 | - switch (format.rate_resolution) { |
1589 | - case wds::CEA640x480p60: |
1590 | - width = 640; |
1591 | - height = 480; |
1592 | - break; |
1593 | - case wds::CEA720x480p60: |
1594 | - case wds::CEA720x480i60: |
1595 | - width = 720; |
1596 | - height = 480; |
1597 | - break; |
1598 | - case wds::CEA720x576p50: |
1599 | - case wds::CEA720x576i50: |
1600 | - width = 720; |
1601 | - height = 576; |
1602 | - break; |
1603 | - case wds::CEA1280x720p30: |
1604 | - case wds::CEA1280x720p60: |
1605 | - width = 1280; |
1606 | - height = 720; |
1607 | - break; |
1608 | - case wds::CEA1920x1080p30: |
1609 | - case wds::CEA1920x1080p60: |
1610 | - case wds::CEA1920x1080i60: |
1611 | - width = 1920; |
1612 | - height = 1080; |
1613 | - break; |
1614 | - case wds::CEA1280x720p25: |
1615 | - case wds::CEA1280x720p50: |
1616 | - case wds::CEA1280x720p24: |
1617 | - width = 1280; |
1618 | - height = 720; |
1619 | - break; |
1620 | - case wds::CEA1920x1080p25: |
1621 | - case wds::CEA1920x1080p50: |
1622 | - case wds::CEA1920x1080i50: |
1623 | - case wds::CEA1920x1080p24: |
1624 | - width = 1920; |
1625 | - height = 1080; |
1626 | - break; |
1627 | - default: |
1628 | - break; |
1629 | - } |
1630 | - break; |
1631 | - default: |
1632 | - break; |
1633 | - } |
1634 | - |
1635 | - std::stringstream ss; |
1636 | - ss << "mirimagesrc mir-socket=/run/mir_socket ! videoconvert ! videoscale ! "; |
1637 | - ss << Utils::Sprintf("video/x-raw,width=%d,height=%d ! ", width, height); |
1638 | - ss << "videoflip method=counterclockwise ! queue2 ! video/x-raw,format=I420 ! "; |
1639 | - ss << "x264enc aud=false byte-stream=true tune=zerolatency ! "; |
1640 | - ss << Utils::Sprintf("video/x-h264,profile=%s ! ", profile.c_str()); |
1641 | - ss << "mpegtsmux ! rtpmp2tpay ! "; |
1642 | - ss << Utils::Sprintf("udpsink name=sink host=%s port=%d", remote_address_.c_str(), sink_port1_); |
1643 | - |
1644 | - GError *error = nullptr; |
1645 | - GstElement *pipeline = gst_parse_launch(ss.str().c_str(), &error); |
1646 | - if (error) { |
1647 | - ERROR("Failed to setup GStreamer pipeline: %s", error->message); |
1648 | - g_error_free(error); |
1649 | - return nullptr; |
1650 | - } |
1651 | +namespace mir { |
1652 | + |
1653 | +SourceMediaManager::SourceMediaManager(const std::string &remote_address) : |
1654 | + remote_address_(remote_address), |
1655 | + output_(mcs::android::H264Encoder::OutputFormat::kRTPAVP) { |
1656 | +} |
1657 | + |
1658 | +SourceMediaManager::~SourceMediaManager() { |
1659 | +} |
1660 | + |
1661 | +SharedGObject<GstElement> SourceMediaManager::ConstructPipeline(const wds::H264VideoFormat &format) { |
1662 | + auto rr = mcs::video::ExtractRateAndResolution(format); |
1663 | + |
1664 | + encoder_ = mcs::android::H264Encoder::Create(output_); |
1665 | + |
1666 | + encoder_->SetDimensions(rr.width, rr.height); |
1667 | + encoder_->SetFramerate(rr.framerate); |
1668 | + |
1669 | + GstElement *pipeline = gst_pipeline_new("video-stream"); |
1670 | + GstElement *source = gst_element_factory_make("fdsrc", "video-in"); |
1671 | + GstElement *sink = gst_element_factory_make("udpsink", "stream-output"); |
1672 | + |
1673 | + // Set the pipeline plugin properties |
1674 | + g_object_set(G_OBJECT(source), "fd", output_.OutputFileDescriptor(), nullptr); |
1675 | + g_object_set(G_OBJECT(sink), "host", remote_address_.c_str(), nullptr); |
1676 | + g_object_set(G_OBJECT(sink), "port", sink_port1_, nullptr); |
1677 | + |
1678 | + gst_bin_add_many(GST_BIN(pipeline), source, sink, nullptr); |
1679 | + gst_element_link_many(source, sink, nullptr); |
1680 | |
1681 | return make_shared_gobject(pipeline); |
1682 | } |
1683 | +} // namespace mir |
1684 | } // namespace mcs |
1685 | |
1686 | === renamed file 'src/mcs/mirsourcemediamanager.h' => 'src/mcs/mir/sourcemediamanager.h' |
1687 | --- src/mcs/mirsourcemediamanager.h 2015-11-30 10:41:56 +0000 |
1688 | +++ src/mcs/mir/sourcemediamanager.h 2016-01-27 13:00:21 +0000 |
1689 | @@ -15,22 +15,30 @@ |
1690 | * |
1691 | */ |
1692 | |
1693 | -#ifndef MIRMEDIAMANAGER_H_ |
1694 | -#define MIRMEDIAMANAGER_H_ |
1695 | +#ifndef MCS_MIR_SOURCEMEDIAMANAGER_H_ |
1696 | +#define MCS_MIR_SOURCEMEDIAMANAGER_H_ |
1697 | |
1698 | -#include "gstsourcemediamanager.h" |
1699 | +#include "mcs/gstsourcemediamanager.h" |
1700 | +#include "mcs/android/h264encoder.h" |
1701 | +#include "mcs/android/pipedoutputtarget.h" |
1702 | |
1703 | namespace mcs { |
1704 | -class MirSourceMediaManager : public GstSourceMediaManager { |
1705 | +namespace mir { |
1706 | + |
1707 | +class SourceMediaManager : public GstSourceMediaManager { |
1708 | public: |
1709 | - explicit MirSourceMediaManager(const std::string &remote_address); |
1710 | - ~MirSourceMediaManager(); |
1711 | + explicit SourceMediaManager(const std::string &remote_address); |
1712 | + ~SourceMediaManager(); |
1713 | |
1714 | protected: |
1715 | SharedGObject<GstElement> ConstructPipeline(const wds::H264VideoFormat &format) override; |
1716 | |
1717 | private: |
1718 | std::string remote_address_; |
1719 | + mcs::android::H264Encoder::Ptr encoder_; |
1720 | + mcs::android::PipedOutputTarget output_; |
1721 | }; |
1722 | +} // namespace mir |
1723 | } // namespace mcs |
1724 | + |
1725 | #endif |
1726 | |
1727 | === modified file 'src/mcs/miracastcontroller.h' |
1728 | --- src/mcs/miracastcontroller.h 2015-12-16 08:04:35 +0000 |
1729 | +++ src/mcs/miracastcontroller.h 2016-01-27 13:00:21 +0000 |
1730 | @@ -21,6 +21,7 @@ |
1731 | #include <chrono> |
1732 | #include <memory> |
1733 | |
1734 | +#include "networkmanager.h" |
1735 | #include "networkdevice.h" |
1736 | #include "non_copyable.h" |
1737 | #include "types.h" |
1738 | @@ -54,7 +55,7 @@ |
1739 | virtual void Scan(const std::chrono::seconds &timeout = std::chrono::seconds{30}) = 0; |
1740 | |
1741 | virtual NetworkDeviceState State() const = 0; |
1742 | - virtual std::vector<NetworkDeviceRole> SupportedRoles() const = 0; |
1743 | + virtual std::vector<NetworkManager::Capability> Capabilities() const = 0; |
1744 | virtual bool Scanning() const = 0; |
1745 | |
1746 | protected: |
1747 | |
1748 | === modified file 'src/mcs/miracastcontrollerskeleton.cpp' |
1749 | --- src/mcs/miracastcontrollerskeleton.cpp 2015-12-21 15:20:11 +0000 |
1750 | +++ src/mcs/miracastcontrollerskeleton.cpp 2016-01-27 13:00:21 +0000 |
1751 | @@ -55,10 +55,7 @@ |
1752 | aethercast_interface_manager_set_state(manager_obj_.get(), |
1753 | NetworkDevice::StateToStr(State()).c_str()); |
1754 | |
1755 | - // Capabilities are a collection of different things our local adapter |
1756 | - // supports. The supported roles are just one part of this. |
1757 | - auto roles = SupportedRoles(); |
1758 | - auto capabilities = DBusHelpers::GenerateCapabilities(roles); |
1759 | + auto capabilities = DBusHelpers::GenerateCapabilities(Capabilities()); |
1760 | |
1761 | aethercast_interface_manager_set_capabilities(manager_obj_.get(), capabilities); |
1762 | |
1763 | |
1764 | === modified file 'src/mcs/miracastservice.cpp' |
1765 | --- src/mcs/miracastservice.cpp 2015-12-18 19:48:09 +0000 |
1766 | +++ src/mcs/miracastservice.cpp 2016-01-27 13:00:21 +0000 |
1767 | @@ -27,8 +27,12 @@ |
1768 | |
1769 | #include <chrono> |
1770 | |
1771 | +#include <boost/filesystem.hpp> |
1772 | + |
1773 | #include <wds/logging.h> |
1774 | |
1775 | +#include "initgstreameronce.h" |
1776 | +#include "config.h" |
1777 | #include "keep_alive.h" |
1778 | #include "logger.h" |
1779 | #include "miracastservice.h" |
1780 | @@ -37,12 +41,11 @@ |
1781 | #include "types.h" |
1782 | #include "logging.h" |
1783 | |
1784 | -#include <w11t/wfddeviceinfo.h> |
1785 | - |
1786 | namespace { |
1787 | // TODO(morphis, tvoss): Expose the port as a construction-time parameter. |
1788 | const std::uint16_t kMiracastDefaultRtspCtrlPort{7236}; |
1789 | const std::chrono::milliseconds kStateIdleTimeout{5000}; |
1790 | +const std::chrono::seconds kShutdownGracePreriod{1}; |
1791 | |
1792 | // SafeLog serves as integration point to the wds::LogSystem world. |
1793 | template <mcs::Logger::Severity severity> |
1794 | @@ -93,11 +96,24 @@ |
1795 | } |
1796 | |
1797 | struct Runtime { |
1798 | - static int OnSignalRaised(gpointer user_data) { |
1799 | + static gboolean OnSignalRaised(gpointer user_data) { |
1800 | auto thiz = static_cast<Runtime*>(user_data); |
1801 | - g_main_loop_quit(thiz->ml); |
1802 | - |
1803 | - return 0; |
1804 | + |
1805 | + // This will bring down everything and the timeout below will give |
1806 | + // things a small amount of time to perform their shutdown jobs. |
1807 | + thiz->service->Shutdown(); |
1808 | + |
1809 | + MCS_DEBUG("Exiting"); |
1810 | + |
1811 | + g_timeout_add_seconds(kShutdownGracePreriod.count(), [](gpointer user_data) { |
1812 | + auto thiz = static_cast<Runtime*>(user_data); |
1813 | + g_main_loop_quit(thiz->ml); |
1814 | + return FALSE; |
1815 | + }, thiz); |
1816 | + |
1817 | + // A second SIGTERM should really terminate us and also overlay |
1818 | + // the grace period for a proper shutdown we're performing. |
1819 | + return FALSE; |
1820 | } |
1821 | |
1822 | Runtime() { |
1823 | @@ -107,6 +123,9 @@ |
1824 | g_unix_signal_add(SIGINT, OnSignalRaised, this); |
1825 | g_unix_signal_add(SIGTERM, OnSignalRaised, this); |
1826 | |
1827 | + // Initialize gstreamer. |
1828 | + mcs::InitGstreamerOnceOrThrow(); |
1829 | + |
1830 | // Redirect all wds logging to our own. |
1831 | wds::LogSystem::set_vlog_func(SafeLog<mcs::Logger::Severity::kTrace>); |
1832 | wds::LogSystem::set_log_func(SafeLog<mcs::Logger::Severity::kInfo>); |
1833 | @@ -140,11 +159,14 @@ |
1834 | // Become a reaper of all our children |
1835 | if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) |
1836 | g_warning("Failed to make us a subreaper of our children"); |
1837 | + |
1838 | + network_manager = mcs::NetworkManagerFactory::Create(); |
1839 | + service = mcs::MiracastService::Create(network_manager); |
1840 | + mcsa = mcs::MiracastControllerSkeleton::create(service); |
1841 | } |
1842 | |
1843 | ~Runtime() { |
1844 | g_main_loop_unref(ml); |
1845 | - gst_deinit(); |
1846 | } |
1847 | |
1848 | void Run() { |
1849 | @@ -153,12 +175,11 @@ |
1850 | |
1851 | GMainLoop *ml = g_main_loop_new(nullptr, FALSE); |
1852 | bool is_gst_initialized = gst_init_check(nullptr, nullptr, nullptr); |
1853 | + mcs::NetworkManager::Ptr network_manager; |
1854 | + mcs::MiracastService::Ptr service; |
1855 | + mcs::MiracastControllerSkeleton::Ptr mcsa; |
1856 | } rt; |
1857 | |
1858 | - auto network_manager = mcs::NetworkManagerFactory::Create(); |
1859 | - auto service = mcs::MiracastService::Create(network_manager); |
1860 | - auto mcsa = mcs::MiracastControllerSkeleton::create(service); |
1861 | - |
1862 | rt.Run(); |
1863 | |
1864 | return 0; |
1865 | @@ -173,6 +194,8 @@ |
1866 | current_state_(kIdle), |
1867 | scan_timeout_source_(0), |
1868 | supported_roles_({kSource}) { |
1869 | + |
1870 | + CreateRuntimeDirectory(); |
1871 | } |
1872 | |
1873 | std::shared_ptr<MiracastService> MiracastService::FinalizeConstruction(const NetworkManager::Ptr &network_manager) { |
1874 | @@ -191,6 +214,15 @@ |
1875 | g_source_remove(scan_timeout_source_); |
1876 | } |
1877 | |
1878 | +void MiracastService::CreateRuntimeDirectory() { |
1879 | + boost::filesystem::path runtime_dir(mcs::kRuntimePath); |
1880 | + |
1881 | + if (boost::filesystem::is_directory(runtime_dir)) |
1882 | + boost::filesystem::remove_all(runtime_dir); |
1883 | + |
1884 | + boost::filesystem::create_directory(runtime_dir); |
1885 | +} |
1886 | + |
1887 | void MiracastService::SetDelegate(const std::weak_ptr<MiracastController::Delegate> &delegate) { |
1888 | delegate_ = delegate; |
1889 | } |
1890 | @@ -203,8 +235,8 @@ |
1891 | return current_state_; |
1892 | } |
1893 | |
1894 | -std::vector<NetworkDeviceRole> MiracastService::SupportedRoles() const { |
1895 | - return supported_roles_; |
1896 | +std::vector<NetworkManager::Capability> MiracastService::Capabilities() const { |
1897 | + return network_manager_->Capabilities(); |
1898 | } |
1899 | |
1900 | bool MiracastService::Scanning() const { |
1901 | @@ -273,6 +305,9 @@ |
1902 | return; |
1903 | |
1904 | AdvanceState(device->State()); |
1905 | + |
1906 | + if (auto sp = delegate_.lock()) |
1907 | + sp->OnDeviceChanged(device); |
1908 | } |
1909 | |
1910 | void MiracastService::OnDeviceChanged(const NetworkDevice::Ptr &device) { |
1911 | @@ -297,7 +332,8 @@ |
1912 | } |
1913 | |
1914 | void MiracastService::StartIdleTimer() { |
1915 | - g_timeout_add(kStateIdleTimeout.count(), &MiracastService::OnIdleTimer, new SharedKeepAlive<MiracastService>{shared_from_this()}); |
1916 | + g_timeout_add(kStateIdleTimeout.count(), &MiracastService::OnIdleTimer, |
1917 | + new SharedKeepAlive<MiracastService>{shared_from_this()}); |
1918 | } |
1919 | |
1920 | void MiracastService::FinishConnectAttempt(mcs::Error error) { |
1921 | @@ -309,6 +345,7 @@ |
1922 | |
1923 | void MiracastService::Connect(const NetworkDevice::Ptr &device, ResultCallback callback) { |
1924 | if (current_device_) { |
1925 | + MCS_DEBUG("Tried to connect again while we're already trying to connect a device"); |
1926 | callback(Error::kAlready); |
1927 | return; |
1928 | } |
1929 | @@ -318,10 +355,10 @@ |
1930 | return; |
1931 | } |
1932 | |
1933 | - DEBUG("Connecting remote device %s", device->Address()); |
1934 | + DEBUG("address %s", device->Address()); |
1935 | |
1936 | if (!network_manager_->Connect(device)) { |
1937 | - DEBUG("FAiled to connect remote device"); |
1938 | + DEBUG("Failed to connect remote device"); |
1939 | callback(Error::kFailed); |
1940 | return; |
1941 | } |
1942 | @@ -347,4 +384,12 @@ |
1943 | void MiracastService::Scan(const std::chrono::seconds &timeout) { |
1944 | network_manager_->Scan(timeout); |
1945 | } |
1946 | + |
1947 | +void MiracastService::Shutdown() { |
1948 | + if (current_device_) |
1949 | + network_manager_->Disconnect(current_device_); |
1950 | + |
1951 | + network_manager_->Release(); |
1952 | +} |
1953 | + |
1954 | } // namespace miracast |
1955 | |
1956 | === modified file 'src/mcs/miracastservice.h' |
1957 | --- src/mcs/miracastservice.h 2015-12-11 21:10:24 +0000 |
1958 | +++ src/mcs/miracastservice.h 2016-01-27 13:00:21 +0000 |
1959 | @@ -67,7 +67,7 @@ |
1960 | void Scan(const std::chrono::seconds &timeout = std::chrono::seconds{30}); |
1961 | |
1962 | NetworkDeviceState State() const; |
1963 | - std::vector<NetworkDeviceRole> SupportedRoles() const; |
1964 | + std::vector<NetworkManager::Capability> Capabilities() const; |
1965 | bool Scanning() const; |
1966 | |
1967 | void OnClientDisconnected(); |
1968 | @@ -91,6 +91,9 @@ |
1969 | void StartIdleTimer(); |
1970 | void LoadWiFiFirmware(); |
1971 | |
1972 | + void Shutdown(); |
1973 | + void CreateRuntimeDirectory(); |
1974 | + |
1975 | private: |
1976 | std::weak_ptr<MiracastController::Delegate> delegate_; |
1977 | std::shared_ptr<NetworkManager> network_manager_; |
1978 | |
1979 | === modified file 'src/mcs/miracastsourceclient.cpp' |
1980 | --- src/mcs/miracastsourceclient.cpp 2015-12-09 16:07:13 +0000 |
1981 | +++ src/mcs/miracastsourceclient.cpp 2016-01-27 13:00:21 +0000 |
1982 | @@ -25,7 +25,7 @@ |
1983 | #include "keep_alive.h" |
1984 | #include "logger.h" |
1985 | #include "miracastsourceclient.h" |
1986 | -#include "mirsourcemediamanager.h" |
1987 | +#include "mcs/mir/sourcemediamanager.h" |
1988 | #include "testsourcemediamanager.h" |
1989 | #include "mediamanagerfactory.h" |
1990 | |
1991 | |
1992 | === modified file 'src/mcs/miracastsourcemanager.cpp' |
1993 | --- src/mcs/miracastsourcemanager.cpp 2015-12-09 16:07:13 +0000 |
1994 | +++ src/mcs/miracastsourcemanager.cpp 2016-01-27 13:00:21 +0000 |
1995 | @@ -24,9 +24,7 @@ |
1996 | namespace mcs { |
1997 | std::shared_ptr<MiracastSourceManager> MiracastSourceManager::Create(const IpV4Address &address, unsigned short port) { |
1998 | auto sp = std::shared_ptr<MiracastSourceManager>{new MiracastSourceManager{}}; |
1999 | - DEBUG("Before setup"); |
2000 | sp->Setup(address, port); |
2001 | - DEBUG("After setup"); |
2002 | return sp; |
2003 | } |
2004 | |
2005 | @@ -52,7 +50,7 @@ |
2006 | } |
2007 | |
2008 | bool MiracastSourceManager::Setup(const IpV4Address &address, unsigned short port) { |
2009 | - GError *error; |
2010 | + GError *error = nullptr; |
2011 | |
2012 | if (socket_) |
2013 | return false; |
2014 | @@ -110,6 +108,8 @@ |
2015 | gboolean MiracastSourceManager::OnNewConnection(GSocket *socket, GIOCondition cond, gpointer user_data) { |
2016 | auto inst = static_cast<WeakKeepAlive<MiracastSourceManager>*>(user_data)->GetInstance().lock(); |
2017 | |
2018 | + MCS_DEBUG(""); |
2019 | + |
2020 | // The callback context was deleted while the wait for connection was active. |
2021 | // Hardly anything we can do about it except for returning early. |
2022 | if (not inst) |
2023 | |
2024 | === modified file 'src/mcs/networkdevice.cpp' |
2025 | --- src/mcs/networkdevice.cpp 2015-12-18 17:15:31 +0000 |
2026 | +++ src/mcs/networkdevice.cpp 2016-01-27 13:00:21 +0000 |
2027 | @@ -17,8 +17,6 @@ |
2028 | |
2029 | #include "networkdevice.h" |
2030 | |
2031 | -#include <w11t/wfddeviceinfo.h> |
2032 | - |
2033 | namespace mcs { |
2034 | std::string NetworkDevice::StateToStr(NetworkDeviceState state) { |
2035 | switch (state) { |
2036 | @@ -27,7 +25,9 @@ |
2037 | case kFailure: |
2038 | return "failure"; |
2039 | case kAssociation: |
2040 | - return "connecting"; |
2041 | + return "association"; |
2042 | + case kConfiguration: |
2043 | + return "configuration"; |
2044 | case kConnected: |
2045 | return "connected"; |
2046 | case kDisconnected: |
2047 | |
2048 | === added file 'src/mcs/networkdeviceskeleton.cpp' |
2049 | --- src/mcs/networkdeviceskeleton.cpp 1970-01-01 00:00:00 +0000 |
2050 | +++ src/mcs/networkdeviceskeleton.cpp 2016-01-27 13:00:21 +0000 |
2051 | @@ -0,0 +1,142 @@ |
2052 | +/* |
2053 | + * Copyright (C) 2015 Canonical, Ltd. |
2054 | + * |
2055 | + * This program is free software: you can redistribute it and/or modify it |
2056 | + * under the terms of the GNU General Public License version 3, as published |
2057 | + * by the Free Software Foundation. |
2058 | + * |
2059 | + * This program is distributed in the hope that it will be useful, but |
2060 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2061 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2062 | + * PURPOSE. See the GNU General Public License for more details. |
2063 | + * |
2064 | + * You should have received a copy of the GNU General Public License along |
2065 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2066 | + * |
2067 | + */ |
2068 | + |
2069 | +#include <algorithm> |
2070 | +#include <boost/concept_check.hpp> |
2071 | + |
2072 | +#include "networkdeviceskeleton.h" |
2073 | +#include "utils.h" |
2074 | +#include "keep_alive.h" |
2075 | +#include "logger.h" |
2076 | +#include "dbushelpers.h" |
2077 | + |
2078 | +namespace mcs { |
2079 | + |
2080 | +NetworkDeviceSkeleton::Ptr NetworkDeviceSkeleton::Create(const SharedGObject<GDBusConnection> &connection, const std::string &path, const NetworkDevice::Ptr &device, const MiracastController::Ptr &controller) { |
2081 | + return std::shared_ptr<NetworkDeviceSkeleton>(new NetworkDeviceSkeleton(connection, path, device, controller))->FinalizeConstruction(); |
2082 | +} |
2083 | + |
2084 | +NetworkDeviceSkeleton::NetworkDeviceSkeleton(const SharedGObject<GDBusConnection> &connection, const std::string &path, const NetworkDevice::Ptr &device, const MiracastController::Ptr &controller) : |
2085 | + ForwardingNetworkDevice(device), |
2086 | + connection_(connection), |
2087 | + object_(make_shared_gobject(aethercast_interface_object_skeleton_new(path.c_str()))), |
2088 | + path_(path), |
2089 | + controller_(controller), |
2090 | + device_iface_(aethercast_interface_device_skeleton_new()) { |
2091 | +} |
2092 | + |
2093 | +std::shared_ptr<NetworkDeviceSkeleton> NetworkDeviceSkeleton::FinalizeConstruction() { |
2094 | + auto sp = shared_from_this(); |
2095 | + |
2096 | + g_signal_connect(device_iface_.get(), "handle-connect", |
2097 | + G_CALLBACK(&NetworkDeviceSkeleton::OnHandleConnect), |
2098 | + new WeakKeepAlive<NetworkDeviceSkeleton>{sp}); |
2099 | + g_signal_connect(device_iface_.get(), "handle-disconnect", |
2100 | + G_CALLBACK(&NetworkDeviceSkeleton::OnHandleDisconnect), |
2101 | + new WeakKeepAlive<NetworkDeviceSkeleton>{sp}); |
2102 | + |
2103 | + SyncProperties(); |
2104 | + |
2105 | + if (!object_) |
2106 | + ERROR("Failed to create object for device %s", Address()); |
2107 | + else |
2108 | + aethercast_interface_object_skeleton_set_device(object_.get(), device_iface_.get()); |
2109 | + |
2110 | + return sp; |
2111 | +} |
2112 | + |
2113 | +void NetworkDeviceSkeleton::SyncProperties() { |
2114 | + aethercast_interface_device_set_address(device_iface_.get(), Address().c_str()); |
2115 | + aethercast_interface_device_set_name(device_iface_.get(), Name().c_str()); |
2116 | + aethercast_interface_device_set_state(device_iface_.get(), NetworkDevice::StateToStr(State()).c_str()); |
2117 | + |
2118 | + auto capabilities = DBusHelpers::GenerateDeviceCapabilities(SupportedRoles()); |
2119 | + aethercast_interface_device_set_capabilities(device_iface_.get(), capabilities); |
2120 | + g_strfreev(capabilities); |
2121 | +} |
2122 | + |
2123 | +GDBusObjectSkeleton* NetworkDeviceSkeleton::DBusObject() const { |
2124 | + return G_DBUS_OBJECT_SKELETON(object_.get()); |
2125 | +} |
2126 | + |
2127 | +std::string NetworkDeviceSkeleton::Path() const { |
2128 | + return path_; |
2129 | +} |
2130 | + |
2131 | +// TODO(tvoss,morphis): Refactor mcs::NetworkDevice to have Connect/Disconnect defined on its interfaces. |
2132 | +// It feels quite dirty to require both an instance of mcs::NetworkDevice and mcs::MiracastController to |
2133 | +// implement the connect/disconnect calls coming in via the bus. The complication then is the async handling of |
2134 | +// the invocation, as we will likely have to reach out to WPASupplicant for example (which is dispatched via the same |
2135 | +// event loop as we are). In addition, we should not start littering our public interfaces by handing down callbacks. |
2136 | +gboolean NetworkDeviceSkeleton::OnHandleConnect(AethercastInterfaceDevice *skeleton, GDBusMethodInvocation *invocation, |
2137 | + const gchar *role, gpointer user_data) |
2138 | +{ |
2139 | + boost::ignore_unused_variable_warning(skeleton); |
2140 | + boost::ignore_unused_variable_warning(role); |
2141 | + |
2142 | + auto inst = static_cast<WeakKeepAlive<NetworkDeviceSkeleton>*>(user_data)->GetInstance().lock(); |
2143 | + |
2144 | + if (not inst) { |
2145 | + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid state"); |
2146 | + return TRUE; |
2147 | + } |
2148 | + |
2149 | + g_object_ref(invocation); |
2150 | + auto inv = make_shared_gobject(invocation); |
2151 | + |
2152 | + inst->controller_->Connect(inst->Fwd(), [inv](mcs::Error error) { |
2153 | + if (error != Error::kNone) { |
2154 | + g_dbus_method_invocation_return_error(inv.get(), G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
2155 | + "%s", mcs::ErrorToString(error).c_str()); |
2156 | + return; |
2157 | + } |
2158 | + |
2159 | + g_dbus_method_invocation_return_value(inv.get(), nullptr); |
2160 | + }); |
2161 | + |
2162 | + return TRUE; |
2163 | +} |
2164 | + |
2165 | +gboolean NetworkDeviceSkeleton::OnHandleDisconnect(AethercastInterfaceDevice *skeleton, GDBusMethodInvocation *invocation, |
2166 | + gpointer user_data) |
2167 | +{ |
2168 | + boost::ignore_unused_variable_warning(skeleton); |
2169 | + |
2170 | + auto inst = static_cast<WeakKeepAlive<NetworkDeviceSkeleton>*>(user_data)->GetInstance().lock(); |
2171 | + |
2172 | + if (not inst) { |
2173 | + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid state"); |
2174 | + return TRUE; |
2175 | + } |
2176 | + |
2177 | + g_object_ref(invocation); |
2178 | + auto inv = make_shared_gobject(invocation); |
2179 | + |
2180 | + inst->controller_->Disconnect(inst->Fwd(), [inv](mcs::Error error) { |
2181 | + if (error != Error::kNone) { |
2182 | + g_dbus_method_invocation_return_error(inv.get(), G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
2183 | + "%s", mcs::ErrorToString(error).c_str()); |
2184 | + return; |
2185 | + } |
2186 | + |
2187 | + g_dbus_method_invocation_return_value(inv.get(), nullptr); |
2188 | + }); |
2189 | + |
2190 | + return TRUE; |
2191 | +} |
2192 | + |
2193 | +} // namespace mcs |
2194 | |
2195 | === removed file 'src/mcs/networkdeviceskeleton.cpp' |
2196 | --- src/mcs/networkdeviceskeleton.cpp 2015-12-21 15:20:11 +0000 |
2197 | +++ src/mcs/networkdeviceskeleton.cpp 1970-01-01 00:00:00 +0000 |
2198 | @@ -1,142 +0,0 @@ |
2199 | -/* |
2200 | - * Copyright (C) 2015 Canonical, Ltd. |
2201 | - * |
2202 | - * This program is free software: you can redistribute it and/or modify it |
2203 | - * under the terms of the GNU General Public License version 3, as published |
2204 | - * by the Free Software Foundation. |
2205 | - * |
2206 | - * This program is distributed in the hope that it will be useful, but |
2207 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
2208 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2209 | - * PURPOSE. See the GNU General Public License for more details. |
2210 | - * |
2211 | - * You should have received a copy of the GNU General Public License along |
2212 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
2213 | - * |
2214 | - */ |
2215 | - |
2216 | -#include <algorithm> |
2217 | -#include <boost/concept_check.hpp> |
2218 | - |
2219 | -#include "networkdeviceskeleton.h" |
2220 | -#include "utils.h" |
2221 | -#include "keep_alive.h" |
2222 | -#include "logger.h" |
2223 | -#include "dbushelpers.h" |
2224 | - |
2225 | -namespace mcs { |
2226 | - |
2227 | -NetworkDeviceSkeleton::Ptr NetworkDeviceSkeleton::Create(const SharedGObject<GDBusConnection> &connection, const std::string &path, const NetworkDevice::Ptr &device, const MiracastController::Ptr &controller) { |
2228 | - return std::shared_ptr<NetworkDeviceSkeleton>(new NetworkDeviceSkeleton(connection, path, device, controller))->FinalizeConstruction(); |
2229 | -} |
2230 | - |
2231 | -NetworkDeviceSkeleton::NetworkDeviceSkeleton(const SharedGObject<GDBusConnection> &connection, const std::string &path, const NetworkDevice::Ptr &device, const MiracastController::Ptr &controller) : |
2232 | - ForwardingNetworkDevice(device), |
2233 | - connection_(connection), |
2234 | - object_(make_shared_gobject(aethercast_interface_object_skeleton_new(path.c_str()))), |
2235 | - path_(path), |
2236 | - controller_(controller), |
2237 | - device_iface_(aethercast_interface_device_skeleton_new()) { |
2238 | -} |
2239 | - |
2240 | -std::shared_ptr<NetworkDeviceSkeleton> NetworkDeviceSkeleton::FinalizeConstruction() { |
2241 | - auto sp = shared_from_this(); |
2242 | - |
2243 | - g_signal_connect(device_iface_.get(), "handle-connect", |
2244 | - G_CALLBACK(&NetworkDeviceSkeleton::OnHandleConnect), |
2245 | - new WeakKeepAlive<NetworkDeviceSkeleton>{sp}); |
2246 | - g_signal_connect(device_iface_.get(), "handle-disconnect", |
2247 | - G_CALLBACK(&NetworkDeviceSkeleton::OnHandleDisconnect), |
2248 | - new WeakKeepAlive<NetworkDeviceSkeleton>{sp}); |
2249 | - |
2250 | - SyncProperties(); |
2251 | - |
2252 | - if (!object_) |
2253 | - ERROR("Failed to create object for device %s", Address()); |
2254 | - else |
2255 | - aethercast_interface_object_skeleton_set_device(object_.get(), device_iface_.get()); |
2256 | - |
2257 | - return sp; |
2258 | -} |
2259 | - |
2260 | -void NetworkDeviceSkeleton::SyncProperties() { |
2261 | - aethercast_interface_device_set_address(device_iface_.get(), Address().c_str()); |
2262 | - aethercast_interface_device_set_name(device_iface_.get(), Name().c_str()); |
2263 | - aethercast_interface_device_set_state(device_iface_.get(), NetworkDevice::StateToStr(State()).c_str()); |
2264 | - |
2265 | - auto capabilities = DBusHelpers::GenerateCapabilities(SupportedRoles()); |
2266 | - aethercast_interface_device_set_capabilities(device_iface_.get(), capabilities); |
2267 | - g_strfreev(capabilities); |
2268 | -} |
2269 | - |
2270 | -GDBusObjectSkeleton* NetworkDeviceSkeleton::DBusObject() const { |
2271 | - return G_DBUS_OBJECT_SKELETON(object_.get()); |
2272 | -} |
2273 | - |
2274 | -std::string NetworkDeviceSkeleton::Path() const { |
2275 | - return path_; |
2276 | -} |
2277 | - |
2278 | -// TODO(tvoss,morphis): Refactor mcs::NetworkDevice to have Connect/Disconnect defined on its interfaces. |
2279 | -// It feels quite dirty to require both an instance of mcs::NetworkDevice and mcs::MiracastController to |
2280 | -// implement the connect/disconnect calls coming in via the bus. The complication then is the async handling of |
2281 | -// the invocation, as we will likely have to reach out to WPASupplicant for example (which is dispatched via the same |
2282 | -// event loop as we are). In addition, we should not start littering our public interfaces by handing down callbacks. |
2283 | -gboolean NetworkDeviceSkeleton::OnHandleConnect(AethercastInterfaceDevice *skeleton, GDBusMethodInvocation *invocation, |
2284 | - const gchar *role, gpointer user_data) |
2285 | -{ |
2286 | - boost::ignore_unused_variable_warning(skeleton); |
2287 | - boost::ignore_unused_variable_warning(role); |
2288 | - |
2289 | - auto inst = static_cast<WeakKeepAlive<NetworkDeviceSkeleton>*>(user_data)->GetInstance().lock(); |
2290 | - |
2291 | - if (not inst) { |
2292 | - g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid state"); |
2293 | - return TRUE; |
2294 | - } |
2295 | - |
2296 | - g_object_ref(invocation); |
2297 | - auto inv = make_shared_gobject(invocation); |
2298 | - |
2299 | - inst->controller_->Connect(inst->Fwd(), [inv](mcs::Error error) { |
2300 | - if (error != Error::kNone) { |
2301 | - g_dbus_method_invocation_return_error(inv.get(), G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
2302 | - "%s", mcs::ErrorToString(error).c_str()); |
2303 | - return; |
2304 | - } |
2305 | - |
2306 | - g_dbus_method_invocation_return_value(inv.get(), nullptr); |
2307 | - }); |
2308 | - |
2309 | - return TRUE; |
2310 | -} |
2311 | - |
2312 | -gboolean NetworkDeviceSkeleton::OnHandleDisconnect(AethercastInterfaceDevice *skeleton, GDBusMethodInvocation *invocation, |
2313 | - gpointer user_data) |
2314 | -{ |
2315 | - boost::ignore_unused_variable_warning(skeleton); |
2316 | - |
2317 | - auto inst = static_cast<WeakKeepAlive<NetworkDeviceSkeleton>*>(user_data)->GetInstance().lock(); |
2318 | - |
2319 | - if (not inst) { |
2320 | - g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid state"); |
2321 | - return TRUE; |
2322 | - } |
2323 | - |
2324 | - g_object_ref(invocation); |
2325 | - auto inv = make_shared_gobject(invocation); |
2326 | - |
2327 | - inst->controller_->Disconnect(inst->Fwd(), [inv](mcs::Error error) { |
2328 | - if (error != Error::kNone) { |
2329 | - g_dbus_method_invocation_return_error(inv.get(), G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
2330 | - "%s", mcs::ErrorToString(error).c_str()); |
2331 | - return; |
2332 | - } |
2333 | - |
2334 | - g_dbus_method_invocation_return_value(inv.get(), nullptr); |
2335 | - }); |
2336 | - |
2337 | - return TRUE; |
2338 | -} |
2339 | - |
2340 | -} // namespace mcs |
2341 | |
2342 | === modified file 'src/mcs/networkmanager.cpp' |
2343 | --- src/mcs/networkmanager.cpp 2015-11-26 16:27:30 +0000 |
2344 | +++ src/mcs/networkmanager.cpp 2016-01-27 13:00:21 +0000 |
2345 | @@ -16,3 +16,13 @@ |
2346 | */ |
2347 | |
2348 | #include "networkmanager.h" |
2349 | + |
2350 | +namespace mcs { |
2351 | +std::string NetworkManager::CapabilityToStr(Capability capability) { |
2352 | + if (capability == Capability::kSink) |
2353 | + return "sink"; |
2354 | + else if (capability == Capability::kSource) |
2355 | + return "source"; |
2356 | + return ""; |
2357 | +} |
2358 | +} // namespace mcs |
2359 | |
2360 | === modified file 'src/mcs/networkmanager.h' |
2361 | --- src/mcs/networkmanager.h 2015-12-09 16:07:13 +0000 |
2362 | +++ src/mcs/networkmanager.h 2016-01-27 13:00:21 +0000 |
2363 | @@ -45,15 +45,25 @@ |
2364 | Delegate() = default; |
2365 | }; |
2366 | |
2367 | + enum class Capability { |
2368 | + kSource, |
2369 | + kSink |
2370 | + }; |
2371 | + |
2372 | + static std::string CapabilityToStr(Capability capability); |
2373 | + |
2374 | virtual void SetDelegate(Delegate * delegate) = 0; |
2375 | |
2376 | + virtual void SetCapabilities(const std::vector<Capability> &capabilities) = 0; |
2377 | + virtual std::vector<Capability> Capabilities() const = 0; |
2378 | + |
2379 | virtual bool Setup() = 0; |
2380 | + virtual void Release() = 0; |
2381 | + |
2382 | virtual void Scan(const std::chrono::seconds &timeout) = 0; |
2383 | virtual bool Connect(const NetworkDevice::Ptr &device) = 0; |
2384 | virtual bool Disconnect(const NetworkDevice::Ptr &device) = 0; |
2385 | |
2386 | - virtual void SetWfdSubElements(const std::list<std::string> &elements) = 0; |
2387 | - |
2388 | virtual std::vector<NetworkDevice::Ptr> Devices() const = 0; |
2389 | virtual IpV4Address LocalAddress() const = 0; |
2390 | virtual bool Running() const = 0; |
2391 | |
2392 | === modified file 'src/mcs/networkmanagerfactory.cpp' |
2393 | --- src/mcs/networkmanagerfactory.cpp 2015-12-18 17:15:31 +0000 |
2394 | +++ src/mcs/networkmanagerfactory.cpp 2016-01-27 13:00:21 +0000 |
2395 | @@ -17,18 +17,81 @@ |
2396 | |
2397 | #include <boost/concept_check.hpp> |
2398 | |
2399 | +#include <w11tng/networkmanager.h> |
2400 | + |
2401 | #include "networkmanagerfactory.h" |
2402 | |
2403 | -#include <w11t/networkmanager.h> |
2404 | +#include "logger.h" |
2405 | +#include "utils.h" |
2406 | |
2407 | namespace mcs { |
2408 | |
2409 | +void NullNetworkManager::SetDelegate(Delegate * delegate) { |
2410 | + ERROR("Not implemented"); |
2411 | +} |
2412 | + |
2413 | +bool NullNetworkManager::Setup() { |
2414 | + ERROR("Not implemented"); |
2415 | + return false; |
2416 | +} |
2417 | + |
2418 | +void NullNetworkManager::Release() { |
2419 | + ERROR("Not implemented"); |
2420 | +} |
2421 | + |
2422 | +void NullNetworkManager::Scan(const std::chrono::seconds &timeout) { |
2423 | + ERROR("Not implemented"); |
2424 | +} |
2425 | + |
2426 | +bool NullNetworkManager::Connect(const NetworkDevice::Ptr &device) { |
2427 | + ERROR("Not implemented"); |
2428 | + return false; |
2429 | +} |
2430 | + |
2431 | +bool NullNetworkManager::Disconnect(const NetworkDevice::Ptr &device) { |
2432 | + ERROR("Not implemented"); |
2433 | + return false; |
2434 | +} |
2435 | + |
2436 | +std::vector<NetworkDevice::Ptr> NullNetworkManager::Devices() const { |
2437 | + ERROR("Not implemented"); |
2438 | + return std::vector<NetworkDevice::Ptr>(); |
2439 | +} |
2440 | + |
2441 | +IpV4Address NullNetworkManager::LocalAddress() const { |
2442 | + ERROR("Not implemented"); |
2443 | + return IpV4Address(); |
2444 | +} |
2445 | + |
2446 | +bool NullNetworkManager::Running() const { |
2447 | + ERROR("Not implemented"); |
2448 | + return false; |
2449 | +} |
2450 | + |
2451 | +bool NullNetworkManager::Scanning() const { |
2452 | + ERROR("Not implemented"); |
2453 | + return false; |
2454 | +} |
2455 | + |
2456 | +void NullNetworkManager::SetCapabilities(const std::vector<Capability> &capabilities) { |
2457 | + ERROR("Not implemented"); |
2458 | +} |
2459 | + |
2460 | +std::vector<NetworkManager::Capability> NullNetworkManager::Capabilities() const { |
2461 | + return std::vector<NetworkManager::Capability>{}; |
2462 | +} |
2463 | + |
2464 | NetworkManager::Ptr NetworkManagerFactory::Create(const std::string &type) { |
2465 | - boost::ignore_unused_variable_warning(type); |
2466 | - |
2467 | - // FIXME for now we only can create the wpa one but this will be extended |
2468 | - // with further types. |
2469 | - return std::make_shared<w11t::NetworkManager>(); |
2470 | + auto final_type = type.length() > 0 ? type : Utils::GetEnvValue("AETHERCAST_NETWORK_MANAGER"); |
2471 | + |
2472 | + DEBUG("Creating network manager of type %s", final_type.length() > 0 ? final_type : "w11tng"); |
2473 | + |
2474 | + // We will always default to the w11t implementation if no invalid |
2475 | + // type is specified. |
2476 | + if (final_type == "w11tng" || final_type.length() == 0) |
2477 | + return w11tng::NetworkManager::Create(); |
2478 | + |
2479 | + return std::make_shared<NullNetworkManager>(); |
2480 | } |
2481 | |
2482 | } // namespace mcs |
2483 | |
2484 | === modified file 'src/mcs/networkmanagerfactory.h' |
2485 | --- src/mcs/networkmanagerfactory.h 2015-12-09 16:07:13 +0000 |
2486 | +++ src/mcs/networkmanagerfactory.h 2016-01-27 13:00:21 +0000 |
2487 | @@ -22,6 +22,27 @@ |
2488 | |
2489 | namespace mcs { |
2490 | |
2491 | +// Only here to make unit testing easier for the factory class |
2492 | +class NullNetworkManager : public mcs::NetworkManager { |
2493 | +public: |
2494 | + void SetDelegate(Delegate * delegate) override; |
2495 | + |
2496 | + bool Setup() override; |
2497 | + void Release() override; |
2498 | + |
2499 | + void Scan(const std::chrono::seconds &timeout) override; |
2500 | + bool Connect(const NetworkDevice::Ptr &device) override; |
2501 | + bool Disconnect(const NetworkDevice::Ptr &device) override; |
2502 | + |
2503 | + std::vector<NetworkDevice::Ptr> Devices() const override; |
2504 | + IpV4Address LocalAddress() const override; |
2505 | + bool Running() const override; |
2506 | + bool Scanning() const override; |
2507 | + |
2508 | + void SetCapabilities(const std::vector<Capability> &capabilities) override; |
2509 | + std::vector<Capability> Capabilities() const override; |
2510 | +}; |
2511 | + |
2512 | class NetworkManagerFactory { |
2513 | public: |
2514 | static NetworkManager::Ptr Create(const std::string &type = ""); |
2515 | |
2516 | === modified file 'src/mcs/networkutils.cpp' |
2517 | --- src/mcs/networkutils.cpp 2015-12-07 16:02:43 +0000 |
2518 | +++ src/mcs/networkutils.cpp 2016-01-27 13:00:21 +0000 |
2519 | @@ -194,6 +194,27 @@ |
2520 | return ifr.ifr_ifindex;; |
2521 | } |
2522 | |
2523 | +std::string NetworkUtils::RetrieveInterfaceName(int index) { |
2524 | + if (index < 0) |
2525 | + return ""; |
2526 | + |
2527 | + auto sock = ::socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); |
2528 | + if (sock < 0) |
2529 | + return ""; |
2530 | + |
2531 | + struct ifreq ifr = { }; |
2532 | + ifr.ifr_ifindex = index; |
2533 | + |
2534 | + auto err = ::ioctl(sock, SIOCGIFNAME, &ifr); |
2535 | + |
2536 | + ::close(sock); |
2537 | + |
2538 | + if (err < 0) |
2539 | + return ""; |
2540 | + |
2541 | + return std::string(ifr.ifr_name); |
2542 | +} |
2543 | + |
2544 | int NetworkUtils::ResetInterface(int index) |
2545 | { |
2546 | struct ifreq ifr, addr_ifr; |
2547 | |
2548 | === modified file 'src/mcs/networkutils.h' |
2549 | --- src/mcs/networkutils.h 2015-11-26 16:48:53 +0000 |
2550 | +++ src/mcs/networkutils.h 2016-01-27 13:00:21 +0000 |
2551 | @@ -23,6 +23,7 @@ |
2552 | { |
2553 | public: |
2554 | static int RetrieveInterfaceIndex(const char *name); |
2555 | + static std::string RetrieveInterfaceName(int index); |
2556 | static int ModifyInterfaceAddress(int cmd, int flags, int index, int family, |
2557 | const char *address, const char *peer, |
2558 | unsigned char prefixlen, const char *broadcast); |
2559 | |
2560 | === modified file 'src/mcs/testsourcemediamanager.cpp' |
2561 | --- src/mcs/testsourcemediamanager.cpp 2015-12-07 16:02:43 +0000 |
2562 | +++ src/mcs/testsourcemediamanager.cpp 2016-01-27 13:00:21 +0000 |
2563 | @@ -15,6 +15,8 @@ |
2564 | * |
2565 | */ |
2566 | |
2567 | +#include <sstream> |
2568 | + |
2569 | #include <gst/gst.h> |
2570 | |
2571 | #include "logger.h" |
2572 | @@ -22,6 +24,8 @@ |
2573 | #include "utils.h" |
2574 | #include "logging.h" |
2575 | |
2576 | +#include "videoformat.h" |
2577 | + |
2578 | namespace mcs { |
2579 | std::shared_ptr<TestSourceMediaManager> TestSourceMediaManager::create(const std::string &remote_address) { |
2580 | return std::shared_ptr<TestSourceMediaManager>{new TestSourceMediaManager{remote_address}}; |
2581 | @@ -35,13 +39,34 @@ |
2582 | } |
2583 | |
2584 | SharedGObject<GstElement> TestSourceMediaManager::ConstructPipeline(const wds::H264VideoFormat &format) { |
2585 | - auto config = Utils::Sprintf("videotestsrc ! videoconvert ! video/x-raw,format=I420 ! x264enc ! mpegtsmux ! rtpmp2tpay ! udpsink name=sink host=%s port=%d", |
2586 | - remote_address_.c_str(), sink_port1_); |
2587 | + auto profile = mcs::video::ExtractH264Profile(format); |
2588 | + auto rr = mcs::video::ExtractRateAndResolution(format); |
2589 | + |
2590 | +#if 0 |
2591 | + std::stringstream ss; |
2592 | + ss << Utils::Sprintf("videotestsrc ! video/x-raw,format=I420,framerate=%d/1,width=%d,height=%d,pixel-aspect-ratio=1/1 ! ", rr.framerate, rr.width, rr.height); |
2593 | + ss << "x264enc tune=zerolatency byte-stream=true ! "; |
2594 | + ss << Utils::Sprintf("video/x-h264,profile=%s ! ", profile.c_str()); |
2595 | + ss << "mpegtsmux ! rtpmp2tpay ! "; |
2596 | + ss << Utils::Sprintf("udpsink name=sink host=%s port=%d", remote_address_.c_str(), sink_port1_); |
2597 | +#else |
2598 | + std::stringstream ss; |
2599 | + ss << "ximagesrc "; |
2600 | + ss << Utils::Sprintf("videoconvert ! video/x-raw,format=I420,framerate=%d/1,pixel-aspect-ratio=1/1 ! ", rr.framerate); |
2601 | + ss << Utils::Sprintf("videoscale ! video/x-raw,width=%d,height=%d ! ", rr.width, rr.height); |
2602 | + ss << "queue2 ! "; |
2603 | + ss << "x264enc byte-stream=true tune=zerolatency interlaced=false ! "; |
2604 | + ss << Utils::Sprintf("video/x-h264,profile=%s !", profile.c_str()); |
2605 | + ss << "mpegtsmux ! rtpmp2tpay ! "; |
2606 | + ss << Utils::Sprintf("udpsink name=sink host=%s port=%d", remote_address_.c_str(), sink_port1_); |
2607 | +#endif |
2608 | + |
2609 | + DEBUG("pipeline: %s", ss.str()); |
2610 | |
2611 | GError *error = nullptr; |
2612 | - GstElement *pipeline = gst_parse_launch(config.c_str(), &error); |
2613 | + GstElement *pipeline = gst_parse_launch(ss.str().c_str(), &error); |
2614 | if (error) { |
2615 | - WARNING("Failed to setup GStreamer pipeline: %s", error->message); |
2616 | + ERROR("Failed to setup GStreamer pipeline: %s", error->message); |
2617 | g_error_free(error); |
2618 | return nullptr; |
2619 | } |
2620 | |
2621 | === modified file 'src/mcs/utils.cpp' |
2622 | --- src/mcs/utils.cpp 2015-12-03 07:43:27 +0000 |
2623 | +++ src/mcs/utils.cpp 2016-01-27 13:00:21 +0000 |
2624 | @@ -15,9 +15,11 @@ |
2625 | * |
2626 | */ |
2627 | |
2628 | +#include <boost/filesystem.hpp> |
2629 | #include <boost/algorithm/string.hpp> |
2630 | |
2631 | #include <memory> |
2632 | +#include <fstream> |
2633 | |
2634 | #include <cstring> |
2635 | #include <cstdarg> |
2636 | @@ -46,4 +48,16 @@ |
2637 | return std::string(""); |
2638 | return std::string(value); |
2639 | } |
2640 | + |
2641 | +bool Utils::CreateFile(const std::string &file_path) { |
2642 | + boost::filesystem::path p(file_path); |
2643 | + if (boost::filesystem::exists(p)) |
2644 | + return false; |
2645 | + |
2646 | + std::ofstream of; |
2647 | + of.open(file_path, std::ofstream::out); |
2648 | + of << ""; |
2649 | + of.close(); |
2650 | + return true; |
2651 | +} |
2652 | } // namespace mcs |
2653 | |
2654 | === modified file 'src/mcs/utils.h' |
2655 | --- src/mcs/utils.h 2015-12-03 07:43:27 +0000 |
2656 | +++ src/mcs/utils.h 2016-01-27 13:00:21 +0000 |
2657 | @@ -40,6 +40,14 @@ |
2658 | static std::string Sprintf(const std::string& fmt_str, Types&&... args); |
2659 | // GetEnv - returns a variable value from the environment |
2660 | static std::string GetEnvValue(const std::string &name); |
2661 | + // CreateFile - create an empty file at the specified path |
2662 | + static bool CreateFile(const std::string &file_path); |
2663 | + |
2664 | + // CreateScopedPtrWithDeleterFor - create a std::unique_ptr with a custom deleter |
2665 | + template <typename Owned, typename Deleter> |
2666 | + inline std::unique_ptr<Owned, Deleter> CreateScopedPtrWithDeleterFor(Owned* owned, Deleter&& deleter) { |
2667 | + return {owned, deleter}; |
2668 | + } |
2669 | }; |
2670 | |
2671 | namespace impl { |
2672 | |
2673 | === added file 'src/mcs/videoformat.cpp' |
2674 | --- src/mcs/videoformat.cpp 1970-01-01 00:00:00 +0000 |
2675 | +++ src/mcs/videoformat.cpp 2016-01-27 13:00:21 +0000 |
2676 | @@ -0,0 +1,383 @@ |
2677 | +/* |
2678 | + * Copyright (C) 2016 Canonical, Ltd. |
2679 | + * |
2680 | + * This program is free software: you can redistribute it and/or modify it |
2681 | + * under the terms of the GNU General Public License version 3, as published |
2682 | + * by the Free Software Foundation. |
2683 | + * |
2684 | + * This program is distributed in the hope that it will be useful, but |
2685 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2686 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2687 | + * PURPOSE. See the GNU General Public License for more details. |
2688 | + * |
2689 | + * You should have received a copy of the GNU General Public License along |
2690 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2691 | + * |
2692 | + */ |
2693 | + |
2694 | +#include "videoformat.h" |
2695 | +#include "logger.h" |
2696 | + |
2697 | +namespace mcs { |
2698 | +namespace video { |
2699 | + |
2700 | +std::string ResolutionTypeToString(wds::ResolutionType type) { |
2701 | + switch (type) { |
2702 | + case wds::CEA: |
2703 | + return "CEA"; |
2704 | + case wds::VESA: |
2705 | + return "VESA"; |
2706 | + case wds::HH: |
2707 | + return "HH"; |
2708 | + default: |
2709 | + break; |
2710 | + } |
2711 | + return "unknown"; |
2712 | +} |
2713 | + |
2714 | +std::string CEARatesAndResolutionsToString(wds::CEARatesAndResolutions type) { |
2715 | + switch (type) { |
2716 | + case wds::CEA640x480p60: |
2717 | + return "640x480p60"; |
2718 | + case wds::CEA720x480p60: |
2719 | + return "720x480p60"; |
2720 | + case wds::CEA720x480i60: |
2721 | + return "720x480i60"; |
2722 | + case wds::CEA720x576p50: |
2723 | + return "720x576p50"; |
2724 | + case wds::CEA720x576i50: |
2725 | + return "720x576i50"; |
2726 | + case wds::CEA1280x720p30: |
2727 | + return "1280x720p30"; |
2728 | + case wds::CEA1280x720p60: |
2729 | + return "1280x720p60"; |
2730 | + case wds::CEA1920x1080p30: |
2731 | + return "1920x1080p30"; |
2732 | + case wds::CEA1920x1080p60: |
2733 | + return "1920x1080p60"; |
2734 | + case wds::CEA1920x1080i60: |
2735 | + return "1920x1080i60"; |
2736 | + case wds::CEA1280x720p25: |
2737 | + return "1280x720p25"; |
2738 | + case wds::CEA1280x720p50: |
2739 | + return "1280x720p50"; |
2740 | + case wds::CEA1920x1080p25: |
2741 | + return "1920x1080p25"; |
2742 | + case wds::CEA1920x1080p50: |
2743 | + return "1920x1080p50"; |
2744 | + case wds::CEA1920x1080i50: |
2745 | + return "1920x1080i50"; |
2746 | + case wds::CEA1280x720p24: |
2747 | + return "1280x720p24"; |
2748 | + case wds::CEA1920x1080p24: |
2749 | + return "1920x1080p24"; |
2750 | + default: |
2751 | + break; |
2752 | + } |
2753 | + return "unknown"; |
2754 | +} |
2755 | + |
2756 | +std::string VESARatesAndResolutionsToString(wds::VESARatesAndResolutions type) { |
2757 | + switch (type) { |
2758 | + case wds::VESA800x600p30: |
2759 | + return "800x600p30"; |
2760 | + case wds::VESA800x600p60: |
2761 | + return "800x600p60"; |
2762 | + case wds::VESA1024x768p30: |
2763 | + return "1024x768p30"; |
2764 | + case wds::VESA1024x768p60: |
2765 | + return "1024x768p60"; |
2766 | + case wds::VESA1152x864p30: |
2767 | + return "1152x864p30"; |
2768 | + case wds::VESA1152x864p60: |
2769 | + return "1152x864p60"; |
2770 | + case wds::VESA1280x768p30: |
2771 | + return "1280x768p30"; |
2772 | + case wds::VESA1280x768p60: |
2773 | + return "1280x768p60"; |
2774 | + case wds::VESA1280x800p30: |
2775 | + return "1280x800p30"; |
2776 | + case wds::VESA1280x800p60: |
2777 | + return "1280x800p60"; |
2778 | + case wds::VESA1360x768p30: |
2779 | + return "1360x768p30"; |
2780 | + case wds::VESA1360x768p60: |
2781 | + return "1360x768p60"; |
2782 | + case wds::VESA1366x768p30: |
2783 | + return "1366x768p30"; |
2784 | + case wds::VESA1366x768p60: |
2785 | + return "1366x768p60"; |
2786 | + case wds::VESA1280x1024p30: |
2787 | + return "1280x1024p30"; |
2788 | + case wds::VESA1280x1024p60: |
2789 | + return "1280x1024p60"; |
2790 | + case wds::VESA1400x1050p30: |
2791 | + return "1400x1050p30"; |
2792 | + case wds::VESA1400x1050p60: |
2793 | + return "1400x1050p60"; |
2794 | + case wds::VESA1440x900p30: |
2795 | + return "1440x900p30"; |
2796 | + case wds::VESA1440x900p60: |
2797 | + return "1440x900p60"; |
2798 | + case wds::VESA1600x900p30: |
2799 | + return "1600x900p30"; |
2800 | + case wds::VESA1600x900p60: |
2801 | + return "1600x900p60"; |
2802 | + case wds::VESA1600x1200p30: |
2803 | + return "1600x1200p30"; |
2804 | + case wds::VESA1600x1200p60: |
2805 | + return "1600x1200p60"; |
2806 | + case wds::VESA1680x1024p30: |
2807 | + return "1680x1024p30"; |
2808 | + case wds::VESA1680x1024p60: |
2809 | + return "1680x1024p60"; |
2810 | + case wds::VESA1680x1050p30: |
2811 | + return "1680x1050p30"; |
2812 | + case wds::VESA1680x1050p60: |
2813 | + return "1680x1050p60"; |
2814 | + case wds::VESA1920x1200p30: |
2815 | + return "1920x1200p30"; |
2816 | + default: |
2817 | + break; |
2818 | + } |
2819 | + return "unknown"; |
2820 | +} |
2821 | + |
2822 | +std::string HHRatesAndResolutionsToString(wds::HHRatesAndResolutions type) { |
2823 | + switch (type) { |
2824 | + case wds::HH800x480p30: |
2825 | + return "800x480p30"; |
2826 | + case wds::HH800x480p60: |
2827 | + return "800x480p60"; |
2828 | + case wds::HH854x480p30: |
2829 | + return "854x480p30"; |
2830 | + case wds::HH854x480p60: |
2831 | + return "854x480p60"; |
2832 | + case wds::HH864x480p30: |
2833 | + return "864x480p30"; |
2834 | + case wds::HH864x480p60: |
2835 | + return "864x480p60"; |
2836 | + case wds::HH640x360p30: |
2837 | + return "640x360p30"; |
2838 | + case wds::HH640x360p60: |
2839 | + return "640x360p60"; |
2840 | + case wds::HH960x540p30: |
2841 | + return "960x540p30"; |
2842 | + case wds::HH960x540p60: |
2843 | + return "960x540p60"; |
2844 | + case wds::HH848x480p30: |
2845 | + return "848x480p30"; |
2846 | + case wds::HH848x480p60: |
2847 | + return "848x480p60"; |
2848 | + default: |
2849 | + break; |
2850 | + } |
2851 | + return "unknown"; |
2852 | +} |
2853 | + |
2854 | +std::string LevelToString(wds::H264Level level) { |
2855 | + switch (level) { |
2856 | + case wds::k3_1: |
2857 | + return "3.1"; |
2858 | + case wds::k3_2: |
2859 | + return "3.2"; |
2860 | + case wds::k4: |
2861 | + return "4"; |
2862 | + case wds::k4_1: |
2863 | + return "4.1"; |
2864 | + case wds::k4_2: |
2865 | + return "4.2"; |
2866 | + default: |
2867 | + break; |
2868 | + } |
2869 | + return "unknown"; |
2870 | +} |
2871 | + |
2872 | +std::string ProfileToString(wds::H264Profile profile) { |
2873 | + switch (profile) { |
2874 | + case wds::CBP: |
2875 | + return "cbp"; |
2876 | + case wds::CHP: |
2877 | + return "chp"; |
2878 | + default: |
2879 | + break; |
2880 | + } |
2881 | + return "unknown"; |
2882 | +} |
2883 | + |
2884 | +void DumpVideoCodec(const wds::H264VideoCodec &codec) { |
2885 | + int i = 0; |
2886 | + |
2887 | + DEBUG(" profile: %s", ProfileToString(codec.profile)); |
2888 | + DEBUG(" level: %s", LevelToString(codec.level)); |
2889 | + |
2890 | + DEBUG(" CEA resolutions: "); |
2891 | + for (i = wds::CEA640x480p60; i <= wds::CEA1920x1080p24; ++i) |
2892 | + if (codec.cea_rr.test(i)) |
2893 | + DEBUG(" %s", CEARatesAndResolutionsToString((wds::CEARatesAndResolutions) i).c_str()); |
2894 | + |
2895 | + DEBUG(" VESA resolutions: "); |
2896 | + for (i = wds::VESA800x600p30; i <= wds::VESA1920x1200p30; ++i) |
2897 | + if (codec.vesa_rr.test(i)) |
2898 | + DEBUG(" %s", VESARatesAndResolutionsToString((wds::VESARatesAndResolutions) i).c_str()); |
2899 | + |
2900 | + DEBUG(" HH resolutions: "); |
2901 | + for (i = wds::HH800x480p30; i <= wds::HH848x480p60; ++i) |
2902 | + if (codec.hh_rr.test(i)) |
2903 | + DEBUG(" %s", HHRatesAndResolutionsToString((wds::HHRatesAndResolutions) i).c_str()); |
2904 | +} |
2905 | + |
2906 | +void DumpVideoFormat(const wds::H264VideoFormat &format) { |
2907 | + DEBUG(" profile: %s", ProfileToString(format.profile)); |
2908 | + DEBUG(" level: %s", LevelToString(format.level)); |
2909 | + DEBUG(" resolution type: %s", ResolutionTypeToString(format.type)); |
2910 | + |
2911 | + if (format.type == wds::CEA) |
2912 | + DEBUG("resolution: %s", CEARatesAndResolutionsToString((wds::CEARatesAndResolutions) format.rate_resolution)); |
2913 | + if (format.type == wds::VESA) |
2914 | + DEBUG("resolution: %s", VESARatesAndResolutionsToString((wds::VESARatesAndResolutions) format.rate_resolution)); |
2915 | + if (format.type == wds::HH) |
2916 | + DEBUG("resolution: %s", HHRatesAndResolutionsToString((wds::HHRatesAndResolutions) format.rate_resolution)); |
2917 | +} |
2918 | + |
2919 | +void DumpNativeFormat(const wds::NativeVideoFormat &format) { |
2920 | + DEBUG(" resolution type: %s", ResolutionTypeToString(format.type)); |
2921 | + |
2922 | + if (format.type == wds::CEA) |
2923 | + DEBUG("resolution: %s", CEARatesAndResolutionsToString((wds::CEARatesAndResolutions) format.rate_resolution)); |
2924 | + if (format.type == wds::VESA) |
2925 | + DEBUG("resolution: %s", VESARatesAndResolutionsToString((wds::VESARatesAndResolutions) format.rate_resolution)); |
2926 | + if (format.type == wds::HH) |
2927 | + DEBUG("resolution: %s", HHRatesAndResolutionsToString((wds::HHRatesAndResolutions) format.rate_resolution)); |
2928 | +} |
2929 | + |
2930 | +std::string ExtractH264Profile(const wds::H264VideoFormat &format) { |
2931 | + std::string profile; |
2932 | + switch (format.profile) { |
2933 | + case wds::CBP: |
2934 | + profile = "constrained-baseline"; |
2935 | + break; |
2936 | + case wds::CHP: |
2937 | + profile = "high"; |
2938 | + break; |
2939 | + default: |
2940 | + break; |
2941 | + } |
2942 | + return profile; |
2943 | +} |
2944 | + |
2945 | +std::string ExtractH264Level(const wds::H264VideoFormat &format) { |
2946 | + std::string level; |
2947 | + switch (format.level) { |
2948 | + case wds::k3_1: |
2949 | + level = "3.1"; |
2950 | + break; |
2951 | + case wds::k3_2: |
2952 | + level = "3.2"; |
2953 | + break; |
2954 | + case wds::k4: |
2955 | + level = "4"; |
2956 | + break; |
2957 | + case wds::k4_1: |
2958 | + level = "4.1"; |
2959 | + break; |
2960 | + case wds::k4_2: |
2961 | + level = "4.2"; |
2962 | + break; |
2963 | + default: |
2964 | + break; |
2965 | + } |
2966 | + return level; |
2967 | +} |
2968 | + |
2969 | +RateAndResolution ExtractRateAndResolution(const wds::H264VideoFormat &format) { |
2970 | + RateAndResolution rr; |
2971 | + switch (format.type) { |
2972 | + case wds::CEA: |
2973 | + switch (format.rate_resolution) { |
2974 | + case wds::CEA640x480p60: |
2975 | + rr.width = 640; |
2976 | + rr.height = 480; |
2977 | + rr.framerate = 60; |
2978 | + break; |
2979 | + case wds::CEA720x480p60: |
2980 | + case wds::CEA720x480i60: |
2981 | + rr.width = 720; |
2982 | + rr.height = 480; |
2983 | + rr.framerate = 60; |
2984 | + break; |
2985 | + case wds::CEA720x576p50: |
2986 | + case wds::CEA720x576i50: |
2987 | + rr.width = 720; |
2988 | + rr.height = 576; |
2989 | + rr.framerate = 50; |
2990 | + break; |
2991 | + case wds::CEA1280x720p30: |
2992 | + rr.width = 1280; |
2993 | + rr.height = 720; |
2994 | + rr.framerate = 30; |
2995 | + break; |
2996 | + case wds::CEA1280x720p60: |
2997 | + rr.width = 1280; |
2998 | + rr.height = 720; |
2999 | + rr.framerate = 60; |
3000 | + break; |
3001 | + case wds::CEA1920x1080p30: |
3002 | + rr.width = 1920; |
3003 | + rr.height = 1080; |
3004 | + rr.framerate = 30; |
3005 | + break; |
3006 | + case wds::CEA1920x1080p60: |
3007 | + case wds::CEA1920x1080i60: |
3008 | + rr.width = 1920; |
3009 | + rr.height = 1080; |
3010 | + rr.framerate = 60; |
3011 | + break; |
3012 | + case wds::CEA1280x720p25: |
3013 | + rr.width = 1280; |
3014 | + rr.height = 720; |
3015 | + rr.framerate = 25; |
3016 | + break; |
3017 | + case wds::CEA1280x720p50: |
3018 | + rr.width = 1280; |
3019 | + rr.height = 720; |
3020 | + rr.framerate = 50; |
3021 | + break; |
3022 | + case wds::CEA1280x720p24: |
3023 | + rr.width = 1280; |
3024 | + rr.height = 720; |
3025 | + rr.framerate = 24; |
3026 | + break; |
3027 | + case wds::CEA1920x1080p25: |
3028 | + rr.width = 1920; |
3029 | + rr.height = 1080; |
3030 | + rr.framerate = 25; |
3031 | + break; |
3032 | + case wds::CEA1920x1080p50: |
3033 | + rr.width = 1920; |
3034 | + rr.height = 1080; |
3035 | + rr.framerate = 50; |
3036 | + break; |
3037 | + case wds::CEA1920x1080i50: |
3038 | + rr.width = 1920; |
3039 | + rr.height = 1080; |
3040 | + rr.framerate = 50; |
3041 | + break; |
3042 | + case wds::CEA1920x1080p24: |
3043 | + rr.width = 1920; |
3044 | + rr.height = 1080; |
3045 | + rr.framerate = 24; |
3046 | + break; |
3047 | + default: |
3048 | + break; |
3049 | + } |
3050 | + break; |
3051 | + // FIXME Add support for VESA and HH |
3052 | + default: |
3053 | + break; |
3054 | + } |
3055 | + return rr; |
3056 | +} |
3057 | + |
3058 | +} // namespace video |
3059 | +} // namespace mcs |
3060 | |
3061 | === added file 'src/mcs/videoformat.h' |
3062 | --- src/mcs/videoformat.h 1970-01-01 00:00:00 +0000 |
3063 | +++ src/mcs/videoformat.h 2016-01-27 13:00:21 +0000 |
3064 | @@ -0,0 +1,43 @@ |
3065 | +/* |
3066 | + * Copyright (C) 2016 Canonical, Ltd. |
3067 | + * |
3068 | + * This program is free software: you can redistribute it and/or modify it |
3069 | + * under the terms of the GNU General Public License version 3, as published |
3070 | + * by the Free Software Foundation. |
3071 | + * |
3072 | + * This program is distributed in the hope that it will be useful, but |
3073 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
3074 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3075 | + * PURPOSE. See the GNU General Public License for more details. |
3076 | + * |
3077 | + * You should have received a copy of the GNU General Public License along |
3078 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
3079 | + * |
3080 | + */ |
3081 | + |
3082 | +#ifndef MCS_VIDEOFORMAT_H_ |
3083 | +#define MCS_VIDEOFORMAT_H_ |
3084 | + |
3085 | +#include <wds/video_format.h> |
3086 | + |
3087 | +namespace mcs { |
3088 | +namespace video { |
3089 | + |
3090 | +void DumpVideoCodec(const wds::H264VideoCodec &codec); |
3091 | +void DumpVideoFormat(const wds::H264VideoFormat &format); |
3092 | +void DumpNativeFormat(const wds::NativeVideoFormat &format); |
3093 | + |
3094 | +struct RateAndResolution { |
3095 | + unsigned int width; |
3096 | + unsigned int height; |
3097 | + unsigned int framerate; |
3098 | +}; |
3099 | + |
3100 | +RateAndResolution ExtractRateAndResolution(const wds::H264VideoFormat &format); |
3101 | +std::string ExtractH264Profile(const wds::H264VideoFormat &format); |
3102 | +std::string ExtractH264Level(const wds::H264VideoFormat &format); |
3103 | + |
3104 | +} // namespace video |
3105 | +} // namespace mcs |
3106 | + |
3107 | +#endif |
3108 | |
3109 | === added file 'src/mcs/x11sourcemediamanager.cpp' |
3110 | --- src/mcs/x11sourcemediamanager.cpp 1970-01-01 00:00:00 +0000 |
3111 | +++ src/mcs/x11sourcemediamanager.cpp 2016-01-27 13:00:21 +0000 |
3112 | @@ -0,0 +1,51 @@ |
3113 | +/* |
3114 | + * Copyright (C) 2015 Canonical, Ltd. |
3115 | + * |
3116 | + * This program is free software: you can redistribute it and/or modify it |
3117 | + * under the terms of the GNU General Public License version 3, as published |
3118 | + * by the Free Software Foundation. |
3119 | + * |
3120 | + * This program is distributed in the hope that it will be useful, but |
3121 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
3122 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3123 | + * PURPOSE. See the GNU General Public License for more details. |
3124 | + * |
3125 | + * You should have received a copy of the GNU General Public License along |
3126 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
3127 | + * |
3128 | + */ |
3129 | + |
3130 | +#include <gst/gst.h> |
3131 | + |
3132 | +#include "logger.h" |
3133 | +#include "x11sourcemediamanager.h" |
3134 | +#include "utils.h" |
3135 | +#include "logging.h" |
3136 | + |
3137 | +namespace mcs { |
3138 | +std::shared_ptr<X11SourceMediaManager> X11SourceMediaManager::create(const std::string &remote_address) { |
3139 | + return std::shared_ptr<X11SourceMediaManager>{new X11SourceMediaManager{remote_address}}; |
3140 | +} |
3141 | + |
3142 | +X11SourceMediaManager::X11SourceMediaManager(const std::string &remote_address) : |
3143 | + remote_address_(remote_address) { |
3144 | +} |
3145 | + |
3146 | +X11SourceMediaManager::~X11SourceMediaManager() { |
3147 | +} |
3148 | + |
3149 | +SharedGObject<GstElement> X11SourceMediaManager::ConstructPipeline(const wds::H264VideoFormat &format) { |
3150 | + auto config = Utils::Sprintf("ximagesrc ! videoconvert ! video/x-raw,format=I420 ! x264enc ! mpegtsmux ! rtpmp2tpay ! udpsink name=sink host=%s port=%d", |
3151 | + remote_address_.c_str(), sink_port1_); |
3152 | + |
3153 | + GError *error = nullptr; |
3154 | + GstElement *pipeline = gst_parse_launch(config.c_str(), &error); |
3155 | + if (error) { |
3156 | + WARNING("Failed to setup GStreamer pipeline: %s", error->message); |
3157 | + g_error_free(error); |
3158 | + return nullptr; |
3159 | + } |
3160 | + |
3161 | + return make_shared_gobject(pipeline); |
3162 | +} |
3163 | +} // namespace mcs |
3164 | |
3165 | === added file 'src/mcs/x11sourcemediamanager.h' |
3166 | --- src/mcs/x11sourcemediamanager.h 1970-01-01 00:00:00 +0000 |
3167 | +++ src/mcs/x11sourcemediamanager.h 2016-01-27 13:00:21 +0000 |
3168 | @@ -0,0 +1,38 @@ |
3169 | +/* |
3170 | + * Copyright (C) 2015 Canonical, Ltd. |
3171 | + * |
3172 | + * This program is free software: you can redistribute it and/or modify it |
3173 | + * under the terms of the GNU General Public License version 3, as published |
3174 | + * by the Free Software Foundation. |
3175 | + * |
3176 | + * This program is distributed in the hope that it will be useful, but |
3177 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
3178 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3179 | + * PURPOSE. See the GNU General Public License for more details. |
3180 | + * |
3181 | + * You should have received a copy of the GNU General Public License along |
3182 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
3183 | + * |
3184 | + */ |
3185 | + |
3186 | +#ifndef X11SOURCEMEDIAMANAGER_H_ |
3187 | +#define X11SOURCEMEDIAMANAGER_H_ |
3188 | + |
3189 | +#include "gstsourcemediamanager.h" |
3190 | + |
3191 | +namespace mcs { |
3192 | +class X11SourceMediaManager : public GstSourceMediaManager { |
3193 | +public: |
3194 | + static std::shared_ptr<X11SourceMediaManager> create(const std::string &remote_address); |
3195 | + ~X11SourceMediaManager(); |
3196 | + |
3197 | +protected: |
3198 | + SharedGObject<GstElement> ConstructPipeline(const wds::H264VideoFormat &format) override; |
3199 | + |
3200 | +private: |
3201 | + explicit X11SourceMediaManager(const std::string &remote_address); |
3202 | + std::string remote_address_; |
3203 | +}; |
3204 | +} // namespace mcs |
3205 | + |
3206 | +#endif |
3207 | |
3208 | === added file 'src/mcs/x264.cpp' |
3209 | --- src/mcs/x264.cpp 1970-01-01 00:00:00 +0000 |
3210 | +++ src/mcs/x264.cpp 2016-01-27 13:00:21 +0000 |
3211 | @@ -0,0 +1,206 @@ |
3212 | +/* |
3213 | + * Copyright (C) 2015 Canonical, Ltd. |
3214 | + * |
3215 | + * This program is free software: you can redistribute it and/or modify it |
3216 | + * under the terms of the GNU General Public License version 3, as published |
3217 | + * by the Free Software Foundation. |
3218 | + * |
3219 | + * This program is distributed in the hope that it will be useful, but |
3220 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
3221 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3222 | + * PURPOSE. See the GNU General Public License for more details. |
3223 | + * |
3224 | + * You should have received a copy of the GNU General Public License along |
3225 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
3226 | + * |
3227 | + */ |
3228 | + |
3229 | +#include <atomic> |
3230 | + |
3231 | +#include "logger.h" |
3232 | +#include "x264.h" |
3233 | + |
3234 | +namespace { |
3235 | + |
3236 | +static std::function<mcs::x264::Encoder::Ptr()>& MutableEncoderFactory() { |
3237 | + static std::function<mcs::x264::Encoder::Ptr()> factory = []() { return mcs::x264::Encoder::Ptr{}; }; |
3238 | + return factory; |
3239 | +} |
3240 | + |
3241 | +static const std::function<mcs::x264::Encoder::Ptr()>& EncoderFactory() { |
3242 | + return MutableEncoderFactory(); |
3243 | +} |
3244 | + |
3245 | +struct McsH264EncoderClass { |
3246 | + static GstStaticPadTemplate* SinkFactory() { |
3247 | + static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( |
3248 | + "sink", |
3249 | + GST_PAD_SINK, |
3250 | + GST_PAD_ALWAYS, |
3251 | + GST_STATIC_CAPS ("ANY")); |
3252 | + return &sink_factory; |
3253 | + } |
3254 | + |
3255 | + static GstStaticPadTemplate* SrcFactory() { |
3256 | + static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ( |
3257 | + "src", |
3258 | + GST_PAD_SRC, |
3259 | + GST_PAD_ALWAYS, |
3260 | + GST_STATIC_CAPS ("ANY")); |
3261 | + |
3262 | + return &src_factory; |
3263 | + } |
3264 | + |
3265 | + static void Init(McsH264EncoderClass *klass); |
3266 | + |
3267 | + GstElementClass parent_class; |
3268 | +}; |
3269 | + |
3270 | +struct McsH264Encoder { |
3271 | + // Data ensures that we can 'new' the object, actually calling |
3272 | + // the ctors of contained objects (mcs::SharedGObject<T>). |
3273 | + struct Data { |
3274 | + mcs::SharedGObject<GstPad> sink; |
3275 | + mcs::SharedGObject<GstPad> source; |
3276 | + mcs::x264::GstEncoder::Ptr impl; |
3277 | + }; |
3278 | + |
3279 | + static GType Type(); |
3280 | + |
3281 | + static McsH264Encoder* CastInstanceFrom(GObject *obj) { |
3282 | + return G_TYPE_CHECK_INSTANCE_CAST(obj,McsH264Encoder::Type(),McsH264Encoder); |
3283 | + } |
3284 | + |
3285 | + static McsH264EncoderClass* CastClassFrom(GObjectClass *klass) { |
3286 | + return G_TYPE_CHECK_CLASS_CAST((klass),McsH264Encoder::Type(),McsH264EncoderClass); |
3287 | + } |
3288 | + |
3289 | + static bool IsInstanceOf(GObject *obj) { |
3290 | + return G_TYPE_CHECK_INSTANCE_TYPE((obj),McsH264Encoder::Type()); |
3291 | + } |
3292 | + |
3293 | + static bool IsClassOf(GObjectClass *klass) { |
3294 | + return G_TYPE_CHECK_CLASS_TYPE((klass),McsH264Encoder::Type()); |
3295 | + } |
3296 | + |
3297 | + static void Init(McsH264Encoder *self) { |
3298 | + MCS_TRACE("self %p", self); |
3299 | + self->d = new McsH264Encoder::Data{ |
3300 | + mcs::make_shared_gobject(gst_pad_new_from_static_template (McsH264EncoderClass::SinkFactory(), "sink")), |
3301 | + mcs::make_shared_gobject(gst_pad_new_from_static_template (McsH264EncoderClass::SrcFactory(), "src")), |
3302 | + std::make_shared<mcs::x264::GstEncoder>(EncoderFactory()()) |
3303 | + }; |
3304 | + |
3305 | + //gst_pad_set_event_function (filter->sinkpad, GST_DEBUG_FUNCPTR(gst_plugin_template_sink_event)); |
3306 | + gst_pad_set_chain_function (self->d->sink.get(), McsH264Encoder::Chain); |
3307 | + |
3308 | + gst_element_add_pad (GST_ELEMENT (self), self->d->sink.get()); |
3309 | + gst_element_add_pad (GST_ELEMENT (self), self->d->source.get()); |
3310 | + } |
3311 | + |
3312 | + static void Finalize(GObject *obj) { |
3313 | + MCS_TRACE("obj %p", obj); |
3314 | + if (auto thiz = CastInstanceFrom(obj)) { |
3315 | + delete thiz->d; |
3316 | + } |
3317 | + } |
3318 | + |
3319 | + static GstFlowReturn Chain(GstPad *pad, GstObject *parent, GstBuffer *buffer) { |
3320 | + MCS_TRACE("Chain(%p, %p, %p)", pad, parent, buffer); |
3321 | + |
3322 | + struct Scope { |
3323 | + ~Scope() { if (buffer) gst_buffer_unref(buffer); } |
3324 | + GstBuffer *buffer; |
3325 | + } scope {buffer}; |
3326 | + |
3327 | + auto result = GST_FLOW_ERROR; |
3328 | + |
3329 | + if (auto thiz = CastInstanceFrom(G_OBJECT(parent))) { |
3330 | + // TODO(tvoss): We should catch exceptions here, return |
3331 | + // appropriate error codes and signal errors to the gst bus. |
3332 | + result = gst_pad_push(thiz->d->source.get(), thiz->d->impl->Encode(buffer)); |
3333 | + } |
3334 | + |
3335 | + return result; |
3336 | + } |
3337 | + |
3338 | + GstElement element; |
3339 | + Data *d; |
3340 | +}; |
3341 | + |
3342 | +#define GST_TYPE_MCS_H264_ENCODER() (gst_mcs_h264_encoder_get_type()) |
3343 | +#define GST_MCS_H264_ENCODER(obj) McsH264Encoder::CastInstanceFrom(obj) |
3344 | +#define GST_MCS_H264_ENCODER_CLASS(klass) McsH264Encoder::CastClassFrom(klass) |
3345 | +#define GST_IS_MCS_H264_ENCODER(obj) McsH264Encoder::IsInstanceOf(obj) |
3346 | +#define GST_IS_MCS_H264_ENCODER_CLASS(klass) McsH264Encoder::IsClassOf(klass) |
3347 | + |
3348 | +GType mcs_h264_encoder_get_type (void); |
3349 | + |
3350 | +G_DEFINE_TYPE(McsH264Encoder, mcs_h264_encoder, GST_TYPE_ELEMENT) |
3351 | + |
3352 | +void McsH264EncoderClass::Init(McsH264EncoderClass *klass) { |
3353 | + MCS_TRACE("klass %p", klass); |
3354 | + |
3355 | + auto gobject_class = reinterpret_cast<GObjectClass*>(klass); |
3356 | + auto gst_element_class = reinterpret_cast<GstElementClass*>(klass); |
3357 | + |
3358 | + gobject_class->finalize = McsH264Encoder::Finalize; |
3359 | + |
3360 | + gst_element_class_set_details_simple(gst_element_class, "ah264", "FIXME(classification)", "FIXME(description)", "Thomas Voß (thomas.voss@canonical.com)"); |
3361 | + gst_element_class_add_pad_template(gst_element_class, gst_static_pad_template_get(McsH264EncoderClass::SinkFactory())); |
3362 | + gst_element_class_add_pad_template(gst_element_class, gst_static_pad_template_get(McsH264EncoderClass::SrcFactory())); |
3363 | +} |
3364 | + |
3365 | +void mcs_h264_encoder_class_init(McsH264EncoderClass *klass) { |
3366 | + McsH264EncoderClass::Init(klass); |
3367 | +} |
3368 | + |
3369 | +void mcs_h264_encoder_init(McsH264Encoder *self) { |
3370 | + McsH264Encoder::Init(self); |
3371 | +} |
3372 | + |
3373 | +GType McsH264Encoder::Type() { |
3374 | + return mcs_h264_encoder_get_type(); |
3375 | +} |
3376 | + |
3377 | +gboolean InitPlugin(GstPlugin* plugin) { |
3378 | + return gst_element_register(plugin, "ah264", 0, McsH264Encoder::Type()); |
3379 | +} |
3380 | +} |
3381 | + |
3382 | +namespace mcs { |
3383 | +namespace x264 { |
3384 | + |
3385 | +bool GstEncoder::Plugin::RegisterWithEncoderFactory(const std::function<Encoder::Ptr()>& factory) { |
3386 | + static bool registered(false); |
3387 | + static std::atomic<bool> once(false); |
3388 | + |
3389 | + if (once.exchange(true)) { |
3390 | + return registered; |
3391 | + } |
3392 | + |
3393 | + MutableEncoderFactory() = factory; |
3394 | + |
3395 | + const auto result = gst_plugin_register_static( |
3396 | + GST_VERSION_MAJOR, |
3397 | + GST_VERSION_MINOR, |
3398 | + mcs::x264::GstEncoder::Plugin::name, |
3399 | + mcs::x264::GstEncoder::Plugin::description, |
3400 | + InitPlugin, |
3401 | + mcs::x264::GstEncoder::Plugin::version, |
3402 | + mcs::x264::GstEncoder::Plugin::license, |
3403 | + mcs::x264::GstEncoder::Plugin::source, |
3404 | + mcs::x264::GstEncoder::Plugin::package, |
3405 | + mcs::x264::GstEncoder::Plugin::origin); |
3406 | + |
3407 | + return registered = result == TRUE; |
3408 | +} |
3409 | + |
3410 | +GstEncoder::GstEncoder(const Encoder::Ptr &encoder) : encoder_(encoder) { |
3411 | +} |
3412 | + |
3413 | +GstBuffer* mcs::x264::GstEncoder::Encode(GstBuffer *buffer) { |
3414 | + return encoder_->Encode(buffer); |
3415 | +} |
3416 | +} |
3417 | +} |
3418 | |
3419 | === added file 'src/mcs/x264.h' |
3420 | --- src/mcs/x264.h 1970-01-01 00:00:00 +0000 |
3421 | +++ src/mcs/x264.h 2016-01-27 13:00:21 +0000 |
3422 | @@ -0,0 +1,82 @@ |
3423 | +/* |
3424 | + * Copyright (C) 2015 Canonical, Ltd. |
3425 | + * |
3426 | + * This program is free software: you can redistribute it and/or modify it |
3427 | + * under the terms of the GNU General Public License version 3, as published |
3428 | + * by the Free Software Foundation. |
3429 | + * |
3430 | + * This program is distributed in the hope that it will be useful, but |
3431 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
3432 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3433 | + * PURPOSE. See the GNU General Public License for more details. |
3434 | + * |
3435 | + * You should have received a copy of the GNU General Public License along |
3436 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
3437 | + * |
3438 | + */ |
3439 | + |
3440 | +#ifndef GSTH264HWENCODER_H_ |
3441 | +#define GSTH264HWENCODER_H_ |
3442 | + |
3443 | +#include <cstdint> |
3444 | +#include <memory> |
3445 | + |
3446 | +#include <gst/gst.h> |
3447 | + |
3448 | +#include "non_copyable.h" |
3449 | +#include "shared_gobject.h" |
3450 | + |
3451 | +namespace mcs { |
3452 | +namespace x264 { |
3453 | +// An Encoder abstracts encoding of MirNativeBuffer |
3454 | +class Encoder : public mcs::NonCopyable { |
3455 | +public: |
3456 | + typedef std::shared_ptr<Encoder> Ptr; |
3457 | + |
3458 | + // Encode takes the nativeBuffer and encodes it, returning |
3459 | + // a Frame instance describing the raw memory segment containing |
3460 | + // the encoded frame. |
3461 | + virtual GstBuffer*Encode(GstBuffer *) = 0; |
3462 | + |
3463 | +protected: |
3464 | + Encoder() = default; |
3465 | +}; |
3466 | + |
3467 | +// A GstEncoder exposes an h264::Encoder to the gstreamer world, |
3468 | +// implemenating an element, that encodes incoming GstBuffer instances. |
3469 | +class GstEncoder { |
3470 | +public: |
3471 | + typedef std::shared_ptr<GstEncoder> Ptr; |
3472 | + |
3473 | + struct Plugin { |
3474 | + static bool RegisterWithEncoderFactory(const std::function<Encoder::Ptr()> &factory); |
3475 | + |
3476 | + static constexpr const char *name = "mcs::h264::Encoder"; |
3477 | + static constexpr const char *description = "h264 encoder leveraging hw-accelerated codecs provided by Android"; |
3478 | + static constexpr const char *version = "0.0"; |
3479 | + static constexpr const char *license = "LGPL"; |
3480 | + static constexpr const char *source = "aethercast"; |
3481 | + static constexpr const char *package = "aethercast"; |
3482 | + static constexpr const char *origin = "https://launchpad.net/aethercast"; |
3483 | + }; |
3484 | + |
3485 | + // GstEncoder creates a new instance, leveraging encoder for carrying out the actual |
3486 | + // encoding. |
3487 | + GstEncoder(const Encoder::Ptr &encoder); |
3488 | + |
3489 | + // SinkPad returns the GstPad describing the sink pad of the element. |
3490 | + SharedGObject<GstPad*> SinkPad() const; |
3491 | + // SourcePad returns the GstPad describing the source pad of the element. |
3492 | + SharedGObject<GstPad*> SourcePad() const; |
3493 | + |
3494 | + // Encode extracts a MirNativeBuffer from the given GstBuffer and hands it on |
3495 | + // to the actual Encoder instance. |
3496 | + GstBuffer* Encode(GstBuffer *buffer); |
3497 | + |
3498 | +private: |
3499 | + Encoder::Ptr encoder_; |
3500 | +}; |
3501 | +} |
3502 | +} |
3503 | + |
3504 | +#endif |
3505 | |
3506 | === removed directory 'src/w11t' |
3507 | === removed file 'src/w11t/commandqueue.cpp' |
3508 | --- src/w11t/commandqueue.cpp 2015-12-18 17:15:31 +0000 |
3509 | +++ src/w11t/commandqueue.cpp 1970-01-01 00:00:00 +0000 |
3510 | @@ -1,103 +0,0 @@ |
3511 | -/* |
3512 | - * Copyright (C) 2015 Canonical, Ltd. |
3513 | - * |
3514 | - * This program is free software: you can redistribute it and/or modify it |
3515 | - * under the terms of the GNU General Public License version 3, as published |
3516 | - * by the Free Software Foundation. |
3517 | - * |
3518 | - * This program is distributed in the hope that it will be useful, but |
3519 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
3520 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3521 | - * PURPOSE. See the GNU General Public License for more details. |
3522 | - * |
3523 | - * You should have received a copy of the GNU General Public License along |
3524 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
3525 | - * |
3526 | - */ |
3527 | - |
3528 | -#include <glib.h> |
3529 | - |
3530 | -#include "commandqueue.h" |
3531 | - |
3532 | -namespace w11t { |
3533 | -CommandQueue::CommandQueue(Delegate *delegate) : |
3534 | - delegate_(delegate), |
3535 | - current_(nullptr), |
3536 | - idle_source_(0) { |
3537 | -} |
3538 | - |
3539 | -CommandQueue::~CommandQueue() { |
3540 | - if (idle_source_ > 0) |
3541 | - g_source_remove(idle_source_); |
3542 | -} |
3543 | - |
3544 | -void CommandQueue::EnqueueCommand(const Message &message, Command::ResponseCallback callback) { |
3545 | - queue_.push(new Command(message, callback)); |
3546 | - RestartQueue(); |
3547 | -} |
3548 | - |
3549 | -void CommandQueue::HandleMessage(Message message) { |
3550 | - if (message.ItsType() == Message::Type::kInvalid) |
3551 | - return; |
3552 | - |
3553 | - if (message.ItsType() == Message::Type::kEvent) { |
3554 | - if (delegate_) |
3555 | - delegate_->OnUnsolicitedResponse(message); |
3556 | - return; |
3557 | - } |
3558 | - |
3559 | - if (!current_) |
3560 | - return; |
3561 | - |
3562 | - if (current_->callback) |
3563 | - current_->callback(message); |
3564 | - |
3565 | - delete current_; |
3566 | - // This will unblock the queue and will allow us to send the next command |
3567 | - current_ = nullptr; |
3568 | - |
3569 | - RestartQueue(); |
3570 | -} |
3571 | - |
3572 | -gboolean CommandQueue::OnRestartQueue(gpointer user_data) { |
3573 | - auto inst = static_cast<CommandQueue*>(user_data); |
3574 | - inst->idle_source_ = 0; |
3575 | - inst->CheckRestartingQueue(); |
3576 | - return FALSE; |
3577 | -} |
3578 | - |
3579 | -void CommandQueue::RestartQueue() { |
3580 | - if (idle_source_ > 0) |
3581 | - return; |
3582 | - |
3583 | - idle_source_ = g_idle_add(&CommandQueue::OnRestartQueue, this); |
3584 | -} |
3585 | - |
3586 | -void CommandQueue::CheckRestartingQueue() { |
3587 | - if (current_ != nullptr || queue_.size() == 0) |
3588 | - return; |
3589 | - |
3590 | - WriteNextCommand(); |
3591 | - RestartQueue(); |
3592 | -} |
3593 | - |
3594 | -void CommandQueue::WriteNextCommand() { |
3595 | - current_ = queue_.front(); |
3596 | - queue_.pop(); |
3597 | - |
3598 | - if (!delegate_) |
3599 | - return; |
3600 | - |
3601 | - if (!current_) |
3602 | - return; |
3603 | - |
3604 | - current_->message.Seal(); |
3605 | - |
3606 | - delegate_->OnWriteMessage(current_->message); |
3607 | - |
3608 | - if (!current_->callback) { |
3609 | - delete current_; |
3610 | - current_ = nullptr; |
3611 | - } |
3612 | -} |
3613 | -} |
3614 | |
3615 | === removed file 'src/w11t/commandqueue.h' |
3616 | --- src/w11t/commandqueue.h 2015-12-18 17:15:31 +0000 |
3617 | +++ src/w11t/commandqueue.h 1970-01-01 00:00:00 +0000 |
3618 | @@ -1,63 +0,0 @@ |
3619 | -/* |
3620 | - * Copyright (C) 2015 Canonical, Ltd. |
3621 | - * |
3622 | - * This program is free software: you can redistribute it and/or modify it |
3623 | - * under the terms of the GNU General Public License version 3, as published |
3624 | - * by the Free Software Foundation. |
3625 | - * |
3626 | - * This program is distributed in the hope that it will be useful, but |
3627 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
3628 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3629 | - * PURPOSE. See the GNU General Public License for more details. |
3630 | - * |
3631 | - * You should have received a copy of the GNU General Public License along |
3632 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
3633 | - * |
3634 | - */ |
3635 | - |
3636 | -#ifndef WPASUPPLICANTCOMMANDQUEUE_H_ |
3637 | -#define WPASUPPLICANTCOMMANDQUEUE_H_ |
3638 | - |
3639 | -#include <boost/noncopyable.hpp> |
3640 | - |
3641 | -#include <string> |
3642 | -#include <queue> |
3643 | - |
3644 | -#include <mcs/non_copyable.h> |
3645 | - |
3646 | -#include "command.h" |
3647 | - |
3648 | -namespace w11t { |
3649 | -class CommandQueue { |
3650 | -public: |
3651 | - class Delegate : private mcs::NonCopyable { |
3652 | - public: |
3653 | - virtual void OnUnsolicitedResponse(Message message) = 0; |
3654 | - virtual void OnWriteMessage(Message message) = 0; |
3655 | - |
3656 | - protected: |
3657 | - Delegate() = default; |
3658 | - }; |
3659 | - |
3660 | - CommandQueue(Delegate *delegate); |
3661 | - ~CommandQueue(); |
3662 | - |
3663 | - void EnqueueCommand(const Message &message, Command::ResponseCallback callback = nullptr); |
3664 | - void HandleMessage(Message message); |
3665 | - |
3666 | -private: |
3667 | - void RestartQueue(); |
3668 | - void CheckRestartingQueue(); |
3669 | - void WriteNextCommand(); |
3670 | - |
3671 | -private: |
3672 | - static gboolean OnRestartQueue(gpointer user_data); |
3673 | - |
3674 | -private: |
3675 | - Delegate *delegate_; |
3676 | - Command *current_; |
3677 | - std::queue<Command*> queue_; |
3678 | - unsigned int idle_source_; |
3679 | -}; |
3680 | -} |
3681 | -#endif |
3682 | |
3683 | === removed file 'src/w11t/dhcpclient.cpp' |
3684 | --- src/w11t/dhcpclient.cpp 2015-12-18 17:15:31 +0000 |
3685 | +++ src/w11t/dhcpclient.cpp 1970-01-01 00:00:00 +0000 |
3686 | @@ -1,102 +0,0 @@ |
3687 | -/* |
3688 | - * Copyright (C) 2015 Canonical, Ltd. |
3689 | - * |
3690 | - * This program is free software: you can redistribute it and/or modify it |
3691 | - * under the terms of the GNU General Public License version 3, as published |
3692 | - * by the Free Software Foundation. |
3693 | - * |
3694 | - * This program is distributed in the hope that it will be useful, but |
3695 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
3696 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3697 | - * PURPOSE. See the GNU General Public License for more details. |
3698 | - * |
3699 | - * You should have received a copy of the GNU General Public License along |
3700 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
3701 | - * |
3702 | - */ |
3703 | - |
3704 | -#include <asm/types.h> |
3705 | -#include <linux/netlink.h> |
3706 | -#include <linux/rtnetlink.h> |
3707 | -#include <sys/socket.h> |
3708 | - |
3709 | -#include <mcs/logger.h> |
3710 | -#include <mcs/networkutils.h> |
3711 | - |
3712 | -#include "dhcpclient.h" |
3713 | -#include "gdhcp.h" |
3714 | - |
3715 | -namespace w11t { |
3716 | -DhcpClient::DhcpClient(Delegate *delegate, const std::string &interface_name) : |
3717 | - delegate_(delegate), |
3718 | - interface_name_(interface_name) { |
3719 | - interface_index_ = mcs::NetworkUtils::RetrieveInterfaceIndex(interface_name_.c_str()); |
3720 | - if (interface_index_ < 0) |
3721 | - MCS_WARNING("Failed to determine index of network interface %s", interface_name_.c_str()); |
3722 | -} |
3723 | - |
3724 | -DhcpClient::~DhcpClient() { |
3725 | -} |
3726 | - |
3727 | -void DhcpClient::OnLeaseAvailable(GDHCPClient *client, gpointer user_data) { |
3728 | - auto inst = static_cast<DhcpClient*>(user_data); |
3729 | - |
3730 | - char *address = g_dhcp_client_get_address(inst->client_); |
3731 | - char *netmask = g_dhcp_client_get_netmask(inst->client_); |
3732 | - |
3733 | - if (!address) { |
3734 | - MCS_WARNING("Received invalid IP configuration over DHCP"); |
3735 | - return; |
3736 | - } |
3737 | - |
3738 | - if (mcs::NetworkUtils::ModifyInterfaceAddress(RTM_NEWADDR, NLM_F_REPLACE | NLM_F_ACK, inst->interface_index_, |
3739 | - AF_INET, address, |
3740 | - NULL, 24, NULL) < 0) { |
3741 | - MCS_WARNING("Failed to assign network address for %s", inst->interface_name_.c_str()); |
3742 | - return; |
3743 | - } |
3744 | - |
3745 | - inst->local_address_ = mcs::IpV4Address::from_string(address); |
3746 | - |
3747 | - if (netmask) |
3748 | - inst->netmask_.assign(netmask); |
3749 | - |
3750 | - inst->delegate_->OnAddressAssigned(inst->local_address_); |
3751 | -} |
3752 | - |
3753 | -void DhcpClient::OnClientDebug(const char *str, gpointer user_data) { |
3754 | - MCS_DEBUG("DHCP: %s", str); |
3755 | -} |
3756 | - |
3757 | -mcs::IpV4Address DhcpClient::LocalAddress() const { |
3758 | - return local_address_; |
3759 | -} |
3760 | - |
3761 | -bool DhcpClient::Start() { |
3762 | - GDHCPClientError error; |
3763 | - client_ = g_dhcp_client_new(G_DHCP_IPV4, interface_index_, &error); |
3764 | - if (!client_) { |
3765 | - MCS_ERROR("Failed to setup DHCP client: %s", g_dhcp_client_error_to_string(error)); |
3766 | - return false; |
3767 | - } |
3768 | - |
3769 | - g_dhcp_client_set_debug(client_, &DhcpClient::OnClientDebug, this); |
3770 | - g_dhcp_client_register_event(client_, G_DHCP_CLIENT_EVENT_LEASE_AVAILABLE, &DhcpClient::OnLeaseAvailable, this); |
3771 | - g_dhcp_client_start(client_, NULL); |
3772 | - |
3773 | - return true; |
3774 | -} |
3775 | - |
3776 | -void DhcpClient::Stop() { |
3777 | - if (!client_) |
3778 | - return; |
3779 | - |
3780 | - g_dhcp_client_stop(client_); |
3781 | - g_dhcp_client_unref(client_); |
3782 | - |
3783 | - local_address_ = mcs::IpV4Address{}; |
3784 | - netmask_ = ""; |
3785 | - |
3786 | - mcs::NetworkUtils::ResetInterface(interface_index_); |
3787 | -} |
3788 | -} |
3789 | |
3790 | === removed file 'src/w11t/dhcpserver.cpp' |
3791 | --- src/w11t/dhcpserver.cpp 2015-12-18 17:15:31 +0000 |
3792 | +++ src/w11t/dhcpserver.cpp 1970-01-01 00:00:00 +0000 |
3793 | @@ -1,99 +0,0 @@ |
3794 | -/* |
3795 | - * Copyright (C) 2015 Canonical, Ltd. |
3796 | - * |
3797 | - * This program is free software: you can redistribute it and/or modify it |
3798 | - * under the terms of the GNU General Public License version 3, as published |
3799 | - * by the Free Software Foundation. |
3800 | - * |
3801 | - * This program is distributed in the hope that it will be useful, but |
3802 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
3803 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3804 | - * PURPOSE. See the GNU General Public License for more details. |
3805 | - * |
3806 | - * You should have received a copy of the GNU General Public License along |
3807 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
3808 | - * |
3809 | - */ |
3810 | - |
3811 | -#include <asm/types.h> |
3812 | -#include <linux/netlink.h> |
3813 | -#include <linux/rtnetlink.h> |
3814 | -#include <sys/socket.h> |
3815 | - |
3816 | -#include <mcs/logger.h> |
3817 | -#include <mcs/networkutils.h> |
3818 | - |
3819 | -#include "dhcpserver.h" |
3820 | - |
3821 | -namespace w11t { |
3822 | -DhcpServer::DhcpServer(Delegate *delegate, const std::string &interface_name) : |
3823 | - interface_name_(interface_name) { |
3824 | - interface_index_ = mcs::NetworkUtils::RetrieveInterfaceIndex(interface_name_.c_str()); |
3825 | - if (interface_index_ < 0) |
3826 | - MCS_ERROR("Failed to determine index of network interface: %s", interface_name_); |
3827 | -} |
3828 | - |
3829 | -DhcpServer::~DhcpServer() { |
3830 | - if (server_) |
3831 | - g_dhcp_server_unref(server_); |
3832 | -} |
3833 | - |
3834 | -mcs::IpV4Address DhcpServer::LocalAddress() const { |
3835 | - // FIXME this should be stored somewhere else |
3836 | - return mcs::IpV4Address::from_string("192.168.7.1"); |
3837 | -} |
3838 | - |
3839 | -void DhcpServer::OnDebug(const char *str, gpointer user_data) { |
3840 | - MCS_DEBUG("DHCP: %s", str); |
3841 | -} |
3842 | - |
3843 | -bool DhcpServer::Start() { |
3844 | - MCS_DEBUG("Starting up DHCP server"); |
3845 | - |
3846 | - // FIXME store those defaults somewhere else |
3847 | - const char *address = "192.168.7.1"; |
3848 | - const char *subnet = "255.255.255.0"; |
3849 | - const char *broadcast = "192.168.7.255"; |
3850 | - unsigned char prefixlen = 24; |
3851 | - |
3852 | - if (mcs::NetworkUtils::ModifyInterfaceAddress(RTM_NEWADDR, NLM_F_REPLACE | NLM_F_ACK, interface_index_, |
3853 | - AF_INET, address, |
3854 | - NULL, prefixlen, broadcast) < 0) { |
3855 | - MCS_ERROR("Failed to assign network address for %s", interface_name_); |
3856 | - return false; |
3857 | - } |
3858 | - |
3859 | - GDHCPServerError error; |
3860 | - server_ = g_dhcp_server_new(G_DHCP_IPV4, interface_index_, &error); |
3861 | - if (!server_) { |
3862 | - MCS_ERROR("Failed to setup DHCP server: %s", g_dhcp_server_error_to_string(error)); |
3863 | - return false; |
3864 | - } |
3865 | - |
3866 | - g_dhcp_server_set_lease_time(server_, 3600); |
3867 | - g_dhcp_server_set_option(server_, G_DHCP_SUBNET, subnet); |
3868 | - g_dhcp_server_set_option(server_, G_DHCP_ROUTER, LocalAddress().to_string().c_str()); |
3869 | - g_dhcp_server_set_option(server_, G_DHCP_DNS_SERVER, NULL); |
3870 | - g_dhcp_server_set_ip_range(server_, "192.168.7.5", "192.168.7.100"); |
3871 | - |
3872 | - g_dhcp_server_set_debug(server_, &DhcpServer::OnDebug, this); |
3873 | - |
3874 | - if(g_dhcp_server_start(server_) < 0) { |
3875 | - MCS_ERROR("Failed to start DHCP server"); |
3876 | - g_dhcp_server_unref(server_); |
3877 | - return false; |
3878 | - } |
3879 | - |
3880 | - return true; |
3881 | -} |
3882 | - |
3883 | -void DhcpServer::Stop() { |
3884 | - if (!server_) |
3885 | - return; |
3886 | - |
3887 | - g_dhcp_server_stop(server_); |
3888 | - g_dhcp_server_unref(server_); |
3889 | - |
3890 | - mcs::NetworkUtils::ResetInterface(interface_index_); |
3891 | -} |
3892 | -} |
3893 | |
3894 | === removed directory 'src/w11t/gdhcp' |
3895 | === removed file 'src/w11t/gdhcp/client.c' |
3896 | --- src/w11t/gdhcp/client.c 2015-12-09 16:07:13 +0000 |
3897 | +++ src/w11t/gdhcp/client.c 1970-01-01 00:00:00 +0000 |
3898 | @@ -1,3282 +0,0 @@ |
3899 | -/* |
3900 | - * |
3901 | - * DHCP client library with GLib integration |
3902 | - * |
3903 | - * Copyright (C) 2009-2014 Intel Corporation. All rights reserved. |
3904 | - * |
3905 | - * This program is free software; you can redistribute it and/or modify |
3906 | - * it under the terms of the GNU General Public License version 2 as |
3907 | - * published by the Free Software Foundation. |
3908 | - * |
3909 | - * This program is distributed in the hope that it will be useful, |
3910 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3911 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3912 | - * GNU General Public License for more details. |
3913 | - * |
3914 | - * You should have received a copy of the GNU General Public License |
3915 | - * along with this program; if not, write to the Free Software |
3916 | - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
3917 | - * |
3918 | - */ |
3919 | - |
3920 | -#ifdef HAVE_CONFIG_H |
3921 | -#include <config.h> |
3922 | -#endif |
3923 | - |
3924 | -#define _GNU_SOURCE |
3925 | -#include <stdio.h> |
3926 | -#include <errno.h> |
3927 | -#include <unistd.h> |
3928 | -#include <stdlib.h> |
3929 | -#include <string.h> |
3930 | -#include <sys/ioctl.h> |
3931 | -#include <arpa/inet.h> |
3932 | -#include <sys/time.h> |
3933 | -#include <resolv.h> |
3934 | - |
3935 | -#include <netpacket/packet.h> |
3936 | -#include <netinet/if_ether.h> |
3937 | -#include <net/ethernet.h> |
3938 | - |
3939 | -#include <linux/if.h> |
3940 | -#include <linux/filter.h> |
3941 | - |
3942 | -#include <glib.h> |
3943 | - |
3944 | -#include "gdhcp.h" |
3945 | -#include "common.h" |
3946 | -#include "ipv4ll.h" |
3947 | - |
3948 | -#define DISCOVER_TIMEOUT 5 |
3949 | -#define DISCOVER_RETRIES 6 |
3950 | - |
3951 | -#define REQUEST_TIMEOUT 5 |
3952 | -#define REQUEST_RETRIES 3 |
3953 | - |
3954 | -typedef enum _listen_mode { |
3955 | - L_NONE, |
3956 | - L2, |
3957 | - L3, |
3958 | - L_ARP, |
3959 | -} ListenMode; |
3960 | - |
3961 | -typedef enum _dhcp_client_state { |
3962 | - INIT_SELECTING, |
3963 | - REBOOTING, |
3964 | - REQUESTING, |
3965 | - BOUND, |
3966 | - RENEWING, |
3967 | - REBINDING, |
3968 | - RELEASED, |
3969 | - IPV4LL_PROBE, |
3970 | - IPV4LL_ANNOUNCE, |
3971 | - IPV4LL_MONITOR, |
3972 | - IPV4LL_DEFEND, |
3973 | - INFORMATION_REQ, |
3974 | - SOLICITATION, |
3975 | - REQUEST, |
3976 | - CONFIRM, |
3977 | - RENEW, |
3978 | - REBIND, |
3979 | - RELEASE, |
3980 | - DECLINE, |
3981 | -} ClientState; |
3982 | - |
3983 | -struct _GDHCPClient { |
3984 | - int ref_count; |
3985 | - GDHCPType type; |
3986 | - ClientState state; |
3987 | - int ifindex; |
3988 | - char *interface; |
3989 | - uint8_t mac_address[6]; |
3990 | - uint32_t xid; |
3991 | - uint32_t server_ip; |
3992 | - uint32_t requested_ip; |
3993 | - char *assigned_ip; |
3994 | - time_t start; |
3995 | - uint32_t lease_seconds; |
3996 | - ListenMode listen_mode; |
3997 | - int listener_sockfd; |
3998 | - uint8_t retry_times; |
3999 | - uint8_t ack_retry_times; |
4000 | - uint8_t conflicts; |
4001 | - guint timeout; |
4002 | - guint t1_timeout; |
4003 | - guint t2_timeout; |
4004 | - guint lease_timeout; |
4005 | - guint listener_watch; |
4006 | - GList *require_list; |
4007 | - GList *request_list; |
4008 | - GHashTable *code_value_hash; |
4009 | - GHashTable *send_value_hash; |
4010 | - GDHCPClientEventFunc lease_available_cb; |
4011 | - gpointer lease_available_data; |
4012 | - GDHCPClientEventFunc ipv4ll_available_cb; |
4013 | - gpointer ipv4ll_available_data; |
4014 | - GDHCPClientEventFunc no_lease_cb; |
4015 | - gpointer no_lease_data; |
4016 | - GDHCPClientEventFunc lease_lost_cb; |
4017 | - gpointer lease_lost_data; |
4018 | - GDHCPClientEventFunc ipv4ll_lost_cb; |
4019 | - gpointer ipv4ll_lost_data; |
4020 | - GDHCPClientEventFunc address_conflict_cb; |
4021 | - gpointer address_conflict_data; |
4022 | - GDHCPDebugFunc debug_func; |
4023 | - gpointer debug_data; |
4024 | - GDHCPClientEventFunc information_req_cb; |
4025 | - gpointer information_req_data; |
4026 | - GDHCPClientEventFunc solicitation_cb; |
4027 | - gpointer solicitation_data; |
4028 | - GDHCPClientEventFunc advertise_cb; |
4029 | - gpointer advertise_data; |
4030 | - GDHCPClientEventFunc request_cb; |
4031 | - gpointer request_data; |
4032 | - GDHCPClientEventFunc renew_cb; |
4033 | - gpointer renew_data; |
4034 | - GDHCPClientEventFunc rebind_cb; |
4035 | - gpointer rebind_data; |
4036 | - GDHCPClientEventFunc release_cb; |
4037 | - gpointer release_data; |
4038 | - GDHCPClientEventFunc confirm_cb; |
4039 | - gpointer confirm_data; |
4040 | - GDHCPClientEventFunc decline_cb; |
4041 | - gpointer decline_data; |
4042 | - char *last_address; |
4043 | - unsigned char *duid; |
4044 | - int duid_len; |
4045 | - unsigned char *server_duid; |
4046 | - int server_duid_len; |
4047 | - uint16_t status_code; |
4048 | - uint32_t iaid; |
4049 | - uint32_t T1, T2; |
4050 | - struct in6_addr ia_na; |
4051 | - struct in6_addr ia_ta; |
4052 | - time_t last_request; |
4053 | - uint32_t expire; |
4054 | - bool retransmit; |
4055 | - struct timeval start_time; |
4056 | - bool request_bcast; |
4057 | -}; |
4058 | - |
4059 | -const char *g_dhcp_client_error_to_string(GDHCPClientError error) { |
4060 | - switch (error) { |
4061 | - case G_DHCP_CLIENT_ERROR_NONE: |
4062 | - return "None"; |
4063 | - case G_DHCP_CLIENT_ERROR_INTERFACE_UNAVAILABLE: |
4064 | - return "Interface unavailable"; |
4065 | - case G_DHCP_CLIENT_ERROR_INTERFACE_IN_USE: |
4066 | - return "Interface in use"; |
4067 | - case G_DHCP_CLIENT_ERROR_INTERFACE_DOWN: |
4068 | - return "Interface down"; |
4069 | - case G_DHCP_CLIENT_ERROR_NOMEM: |
4070 | - return "No memory"; |
4071 | - case G_DHCP_CLIENT_ERROR_INVALID_INDEX: |
4072 | - return "Invalid index"; |
4073 | - case G_DHCP_CLIENT_ERROR_INVALID_OPTION: |
4074 | - return "Invalid option"; |
4075 | - default: |
4076 | - break; |
4077 | - } |
4078 | - |
4079 | - return ""; |
4080 | -} |
4081 | - |
4082 | -static inline void debug(GDHCPClient *client, const char *format, ...) |
4083 | -{ |
4084 | - char str[256]; |
4085 | - va_list ap; |
4086 | - |
4087 | - if (!client->debug_func) |
4088 | - return; |
4089 | - |
4090 | - va_start(ap, format); |
4091 | - |
4092 | - if (vsnprintf(str, sizeof(str), format, ap) > 0) |
4093 | - client->debug_func(str, client->debug_data); |
4094 | - |
4095 | - va_end(ap); |
4096 | -} |
4097 | - |
4098 | -/* Initialize the packet with the proper defaults */ |
4099 | -static void init_packet(GDHCPClient *dhcp_client, gpointer pkt, char type) |
4100 | -{ |
4101 | - if (dhcp_client->type == G_DHCP_IPV6) |
4102 | - dhcpv6_init_header(pkt, type); |
4103 | - else { |
4104 | - struct dhcp_packet *packet = pkt; |
4105 | - |
4106 | - dhcp_init_header(packet, type); |
4107 | - memcpy(packet->chaddr, dhcp_client->mac_address, 6); |
4108 | - } |
4109 | -} |
4110 | - |
4111 | -static void add_request_options(GDHCPClient *dhcp_client, |
4112 | - struct dhcp_packet *packet) |
4113 | -{ |
4114 | - int len = 0; |
4115 | - GList *list; |
4116 | - uint8_t code; |
4117 | - int end = dhcp_end_option(packet->options); |
4118 | - |
4119 | - for (list = dhcp_client->request_list; list; list = list->next) { |
4120 | - code = (uint8_t) GPOINTER_TO_INT(list->data); |
4121 | - |
4122 | - packet->options[end + OPT_DATA + len] = code; |
4123 | - len++; |
4124 | - } |
4125 | - |
4126 | - if (len) { |
4127 | - packet->options[end + OPT_CODE] = DHCP_PARAM_REQ; |
4128 | - packet->options[end + OPT_LEN] = len; |
4129 | - packet->options[end + OPT_DATA + len] = DHCP_END; |
4130 | - } |
4131 | -} |
4132 | - |
4133 | -struct hash_params { |
4134 | - unsigned char *buf; |
4135 | - int max_buf; |
4136 | - unsigned char **ptr_buf; |
4137 | -}; |
4138 | - |
4139 | -static void add_dhcpv6_binary_option(gpointer key, gpointer value, |
4140 | - gpointer user_data) |
4141 | -{ |
4142 | - uint8_t *option = value; |
4143 | - uint16_t len; |
4144 | - struct hash_params *params = user_data; |
4145 | - |
4146 | - /* option[0][1] contains option code */ |
4147 | - len = option[2] << 8 | option[3]; |
4148 | - |
4149 | - if ((*params->ptr_buf + len + 2 + 2) > (params->buf + params->max_buf)) |
4150 | - return; |
4151 | - |
4152 | - memcpy(*params->ptr_buf, option, len + 2 + 2); |
4153 | - (*params->ptr_buf) += len + 2 + 2; |
4154 | -} |
4155 | - |
4156 | -static void add_dhcpv6_send_options(GDHCPClient *dhcp_client, |
4157 | - unsigned char *buf, int max_buf, |
4158 | - unsigned char **ptr_buf) |
4159 | -{ |
4160 | - struct hash_params params = { |
4161 | - .buf = buf, |
4162 | - .max_buf = max_buf, |
4163 | - .ptr_buf = ptr_buf |
4164 | - }; |
4165 | - |
4166 | - if (dhcp_client->type != G_DHCP_IPV6) |
4167 | - return; |
4168 | - |
4169 | - g_hash_table_foreach(dhcp_client->send_value_hash, |
4170 | - add_dhcpv6_binary_option, ¶ms); |
4171 | - |
4172 | - *ptr_buf = *params.ptr_buf; |
4173 | -} |
4174 | - |
4175 | -static void copy_option(uint8_t *buf, uint16_t code, uint16_t len, |
4176 | - uint8_t *msg) |
4177 | -{ |
4178 | - buf[0] = code >> 8; |
4179 | - buf[1] = code & 0xff; |
4180 | - buf[2] = len >> 8; |
4181 | - buf[3] = len & 0xff; |
4182 | - if (len > 0 && msg) |
4183 | - memcpy(&buf[4], msg, len); |
4184 | -} |
4185 | - |
4186 | -static int32_t get_time_diff(struct timeval *tv) |
4187 | -{ |
4188 | - struct timeval now; |
4189 | - int32_t hsec; |
4190 | - |
4191 | - gettimeofday(&now, NULL); |
4192 | - |
4193 | - hsec = (now.tv_sec - tv->tv_sec) * 100; |
4194 | - hsec += (now.tv_usec - tv->tv_usec) / 10000; |
4195 | - |
4196 | - return hsec; |
4197 | -} |
4198 | - |
4199 | -static void remove_timeouts(GDHCPClient *dhcp_client) |
4200 | -{ |
4201 | - |
4202 | - if (dhcp_client->timeout > 0) |
4203 | - g_source_remove(dhcp_client->timeout); |
4204 | - if (dhcp_client->t1_timeout > 0) |
4205 | - g_source_remove(dhcp_client->t1_timeout); |
4206 | - if (dhcp_client->t2_timeout > 0) |
4207 | - g_source_remove(dhcp_client->t2_timeout); |
4208 | - if (dhcp_client->lease_timeout > 0) |
4209 | - g_source_remove(dhcp_client->lease_timeout); |
4210 | - |
4211 | - dhcp_client->timeout = 0; |
4212 | - dhcp_client->t1_timeout = 0; |
4213 | - dhcp_client->t2_timeout = 0; |
4214 | - dhcp_client->lease_timeout = 0; |
4215 | - |
4216 | -} |
4217 | - |
4218 | -static void add_dhcpv6_request_options(GDHCPClient *dhcp_client, |
4219 | - struct dhcpv6_packet *packet, |
4220 | - unsigned char *buf, int max_buf, |
4221 | - unsigned char **ptr_buf) |
4222 | -{ |
4223 | - GList *list; |
4224 | - uint16_t code, value; |
4225 | - bool added; |
4226 | - int32_t diff; |
4227 | - int len; |
4228 | - |
4229 | - if (dhcp_client->type != G_DHCP_IPV6) |
4230 | - return; |
4231 | - |
4232 | - for (list = dhcp_client->request_list; list; list = list->next) { |
4233 | - code = (uint16_t) GPOINTER_TO_INT(list->data); |
4234 | - added = false; |
4235 | - |
4236 | - switch (code) { |
4237 | - case G_DHCPV6_CLIENTID: |
4238 | - if (!dhcp_client->duid) |
4239 | - return; |
4240 | - |
4241 | - len = 2 + 2 + dhcp_client->duid_len; |
4242 | - if ((*ptr_buf + len) > (buf + max_buf)) { |
4243 | - debug(dhcp_client, "Too long dhcpv6 message " |
4244 | - "when writing client id option"); |
4245 | - return; |
4246 | - } |
4247 | - |
4248 | - copy_option(*ptr_buf, G_DHCPV6_CLIENTID, |
4249 | - dhcp_client->duid_len, dhcp_client->duid); |
4250 | - (*ptr_buf) += len; |
4251 | - added = true; |
4252 | - break; |
4253 | - |
4254 | - case G_DHCPV6_SERVERID: |
4255 | - if (!dhcp_client->server_duid) |
4256 | - break; |
4257 | - |
4258 | - len = 2 + 2 + dhcp_client->server_duid_len; |
4259 | - if ((*ptr_buf + len) > (buf + max_buf)) { |
4260 | - debug(dhcp_client, "Too long dhcpv6 message " |
4261 | - "when writing server id option"); |
4262 | - return; |
4263 | - } |
4264 | - |
4265 | - copy_option(*ptr_buf, G_DHCPV6_SERVERID, |
4266 | - dhcp_client->server_duid_len, |
4267 | - dhcp_client->server_duid); |
4268 | - (*ptr_buf) += len; |
4269 | - added = true; |
4270 | - break; |
4271 | - |
4272 | - case G_DHCPV6_RAPID_COMMIT: |
4273 | - len = 2 + 2; |
4274 | - if ((*ptr_buf + len) > (buf + max_buf)) { |
4275 | - debug(dhcp_client, "Too long dhcpv6 message " |
4276 | - "when writing rapid commit option"); |
4277 | - return; |
4278 | - } |
4279 | - |
4280 | - copy_option(*ptr_buf, G_DHCPV6_RAPID_COMMIT, 0, 0); |
4281 | - (*ptr_buf) += len; |
4282 | - added = true; |
4283 | - break; |
4284 | - |
4285 | - case G_DHCPV6_ORO: |
4286 | - break; |
4287 | - |
4288 | - case G_DHCPV6_ELAPSED_TIME: |
4289 | - if (!dhcp_client->retransmit) { |
4290 | - /* |
4291 | - * Initial message, elapsed time is 0. |
4292 | - */ |
4293 | - diff = 0; |
4294 | - } else { |
4295 | - diff = get_time_diff(&dhcp_client->start_time); |
4296 | - if (diff < 0 || diff > 0xffff) |
4297 | - diff = 0xffff; |
4298 | - } |
4299 | - |
4300 | - len = 2 + 2 + 2; |
4301 | - if ((*ptr_buf + len) > (buf + max_buf)) { |
4302 | - debug(dhcp_client, "Too long dhcpv6 message " |
4303 | - "when writing elapsed time option"); |
4304 | - return; |
4305 | - } |
4306 | - |
4307 | - value = htons((uint16_t)diff); |
4308 | - copy_option(*ptr_buf, G_DHCPV6_ELAPSED_TIME, |
4309 | - 2, (uint8_t *)&value); |
4310 | - (*ptr_buf) += len; |
4311 | - added = true; |
4312 | - break; |
4313 | - |
4314 | - case G_DHCPV6_DNS_SERVERS: |
4315 | - break; |
4316 | - |
4317 | - case G_DHCPV6_DOMAIN_LIST: |
4318 | - break; |
4319 | - |
4320 | - case G_DHCPV6_SNTP_SERVERS: |
4321 | - break; |
4322 | - |
4323 | - default: |
4324 | - break; |
4325 | - } |
4326 | - |
4327 | - if (added) |
4328 | - debug(dhcp_client, "option %d len %d added", code, len); |
4329 | - } |
4330 | -} |
4331 | - |
4332 | -static void add_binary_option(gpointer key, gpointer value, gpointer user_data) |
4333 | -{ |
4334 | - uint8_t *option = value; |
4335 | - struct dhcp_packet *packet = user_data; |
4336 | - |
4337 | - dhcp_add_binary_option(packet, option); |
4338 | -} |
4339 | - |
4340 | -static void add_send_options(GDHCPClient *dhcp_client, |
4341 | - struct dhcp_packet *packet) |
4342 | -{ |
4343 | - g_hash_table_foreach(dhcp_client->send_value_hash, |
4344 | - add_binary_option, packet); |
4345 | -} |
4346 | - |
4347 | -/* |
4348 | - * Return an RFC 951- and 2131-complaint BOOTP 'secs' value that |
4349 | - * represents the number of seconds elapsed from the start of |
4350 | - * attempting DHCP to satisfy some DHCP servers that allow for an |
4351 | - * "authoritative" reply before responding. |
4352 | - */ |
4353 | -static uint16_t dhcp_attempt_secs(GDHCPClient *dhcp_client) |
4354 | -{ |
4355 | - return htons(MIN(time(NULL) - dhcp_client->start, UINT16_MAX)); |
4356 | -} |
4357 | - |
4358 | -static int send_discover(GDHCPClient *dhcp_client, uint32_t requested) |
4359 | -{ |
4360 | - struct dhcp_packet packet; |
4361 | - |
4362 | - debug(dhcp_client, "sending DHCP discover request"); |
4363 | - |
4364 | - init_packet(dhcp_client, &packet, DHCPDISCOVER); |
4365 | - |
4366 | - packet.xid = dhcp_client->xid; |
4367 | - packet.secs = dhcp_attempt_secs(dhcp_client); |
4368 | - |
4369 | - if (requested) |
4370 | - dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP, requested); |
4371 | - |
4372 | - /* Explicitly saying that we want RFC-compliant packets helps |
4373 | - * some buggy DHCP servers to NOT send bigger packets */ |
4374 | - dhcp_add_option_uint16(&packet, DHCP_MAX_SIZE, 576); |
4375 | - |
4376 | - add_request_options(dhcp_client, &packet); |
4377 | - |
4378 | - add_send_options(dhcp_client, &packet); |
4379 | - |
4380 | - /* |
4381 | - * If we do not get a reply to DISCOVER packet, then we try with |
4382 | - * broadcast flag set. So first packet is sent without broadcast flag, |
4383 | - * first retry is with broadcast flag, second retry is without it etc. |
4384 | - * Reason is various buggy routers/AP that either eat the other or vice |
4385 | - * versa. In the receiving side we then find out what kind of packet |
4386 | - * the server can send. |
4387 | - */ |
4388 | - return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, |
4389 | - INADDR_BROADCAST, SERVER_PORT, |
4390 | - MAC_BCAST_ADDR, dhcp_client->ifindex, |
4391 | - dhcp_client->retry_times % 2); |
4392 | -} |
4393 | - |
4394 | -static int send_request(GDHCPClient *dhcp_client) |
4395 | -{ |
4396 | - struct dhcp_packet packet; |
4397 | - |
4398 | - debug(dhcp_client, "sending DHCP request (state %d)", |
4399 | - dhcp_client->state); |
4400 | - |
4401 | - init_packet(dhcp_client, &packet, DHCPREQUEST); |
4402 | - |
4403 | - packet.xid = dhcp_client->xid; |
4404 | - packet.secs = dhcp_attempt_secs(dhcp_client); |
4405 | - |
4406 | - if (dhcp_client->state == REQUESTING || dhcp_client->state == REBOOTING) |
4407 | - dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP, |
4408 | - dhcp_client->requested_ip); |
4409 | - |
4410 | - if (dhcp_client->state == REQUESTING) |
4411 | - dhcp_add_option_uint32(&packet, DHCP_SERVER_ID, |
4412 | - dhcp_client->server_ip); |
4413 | - |
4414 | - dhcp_add_option_uint16(&packet, DHCP_MAX_SIZE, 576); |
4415 | - |
4416 | - add_request_options(dhcp_client, &packet); |
4417 | - |
4418 | - add_send_options(dhcp_client, &packet); |
4419 | - |
4420 | - if (dhcp_client->state == RENEWING || dhcp_client->state == REBINDING) |
4421 | - packet.ciaddr = htonl(dhcp_client->requested_ip); |
4422 | - |
4423 | - if (dhcp_client->state == RENEWING) |
4424 | - return dhcp_send_kernel_packet(&packet, |
4425 | - dhcp_client->requested_ip, CLIENT_PORT, |
4426 | - dhcp_client->server_ip, SERVER_PORT); |
4427 | - |
4428 | - return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, |
4429 | - INADDR_BROADCAST, SERVER_PORT, |
4430 | - MAC_BCAST_ADDR, dhcp_client->ifindex, |
4431 | - dhcp_client->request_bcast); |
4432 | -} |
4433 | - |
4434 | -static int send_release(GDHCPClient *dhcp_client, |
4435 | - uint32_t server, uint32_t ciaddr) |
4436 | -{ |
4437 | - struct dhcp_packet packet; |
4438 | - uint64_t rand; |
4439 | - |
4440 | - debug(dhcp_client, "sending DHCP release request"); |
4441 | - |
4442 | - init_packet(dhcp_client, &packet, DHCPRELEASE); |
4443 | - dhcp_get_random(&rand); |
4444 | - packet.xid = rand; |
4445 | - packet.ciaddr = htonl(ciaddr); |
4446 | - |
4447 | - dhcp_add_option_uint32(&packet, DHCP_SERVER_ID, server); |
4448 | - |
4449 | - return dhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, |
4450 | - server, SERVER_PORT); |
4451 | -} |
4452 | - |
4453 | -static gboolean ipv4ll_probe_timeout(gpointer dhcp_data); |
4454 | -static int switch_listening_mode(GDHCPClient *dhcp_client, |
4455 | - ListenMode listen_mode); |
4456 | - |
4457 | -static gboolean send_probe_packet(gpointer dhcp_data) |
4458 | -{ |
4459 | - GDHCPClient *dhcp_client; |
4460 | - guint timeout; |
4461 | - |
4462 | - dhcp_client = dhcp_data; |
4463 | - /* if requested_ip is not valid, pick a new address*/ |
4464 | - if (dhcp_client->requested_ip == 0) { |
4465 | - debug(dhcp_client, "pick a new random address"); |
4466 | - dhcp_client->requested_ip = ipv4ll_random_ip(); |
4467 | - } |
4468 | - |
4469 | - debug(dhcp_client, "sending IPV4LL probe request"); |
4470 | - |
4471 | - if (dhcp_client->retry_times == 1) { |
4472 | - dhcp_client->state = IPV4LL_PROBE; |
4473 | - switch_listening_mode(dhcp_client, L_ARP); |
4474 | - } |
4475 | - ipv4ll_send_arp_packet(dhcp_client->mac_address, 0, |
4476 | - dhcp_client->requested_ip, dhcp_client->ifindex); |
4477 | - |
4478 | - if (dhcp_client->retry_times < PROBE_NUM) { |
4479 | - /*add a random timeout in range of PROBE_MIN to PROBE_MAX*/ |
4480 | - timeout = ipv4ll_random_delay_ms(PROBE_MAX-PROBE_MIN); |
4481 | - timeout += PROBE_MIN*1000; |
4482 | - } else |
4483 | - timeout = (ANNOUNCE_WAIT * 1000); |
4484 | - |
4485 | - dhcp_client->timeout = g_timeout_add_full(G_PRIORITY_HIGH, |
4486 | - timeout, |
4487 | - ipv4ll_probe_timeout, |
4488 | - dhcp_client, |
4489 | - NULL); |
4490 | - return FALSE; |
4491 | -} |
4492 | - |
4493 | -static gboolean ipv4ll_announce_timeout(gpointer dhcp_data); |
4494 | -static gboolean ipv4ll_defend_timeout(gpointer dhcp_data); |
4495 | - |
4496 | -static gboolean send_announce_packet(gpointer dhcp_data) |
4497 | -{ |
4498 | - GDHCPClient *dhcp_client; |
4499 | - |
4500 | - dhcp_client = dhcp_data; |
4501 | - |
4502 | - debug(dhcp_client, "sending IPV4LL announce request"); |
4503 | - |
4504 | - ipv4ll_send_arp_packet(dhcp_client->mac_address, |
4505 | - dhcp_client->requested_ip, |
4506 | - dhcp_client->requested_ip, |
4507 | - dhcp_client->ifindex); |
4508 | - |
4509 | - remove_timeouts(dhcp_client); |
4510 | - |
4511 | - if (dhcp_client->state == IPV4LL_DEFEND) { |
4512 | - dhcp_client->timeout = |
4513 | - g_timeout_add_seconds_full(G_PRIORITY_HIGH, |
4514 | - DEFEND_INTERVAL, |
4515 | - ipv4ll_defend_timeout, |
4516 | - dhcp_client, |
4517 | - NULL); |
4518 | - return TRUE; |
4519 | - } else |
4520 | - dhcp_client->timeout = |
4521 | - g_timeout_add_seconds_full(G_PRIORITY_HIGH, |
4522 | - ANNOUNCE_INTERVAL, |
4523 | - ipv4ll_announce_timeout, |
4524 | - dhcp_client, |
4525 | - NULL); |
4526 | - return TRUE; |
4527 | -} |
4528 | - |
4529 | -static void get_interface_mac_address(int index, uint8_t *mac_address) |
4530 | -{ |
4531 | - struct ifreq ifr; |
4532 | - int sk, err; |
4533 | - |
4534 | - sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); |
4535 | - if (sk < 0) { |
4536 | - perror("Open socket error"); |
4537 | - return; |
4538 | - } |
4539 | - |
4540 | - memset(&ifr, 0, sizeof(ifr)); |
4541 | - ifr.ifr_ifindex = index; |
4542 | - |
4543 | - err = ioctl(sk, SIOCGIFNAME, &ifr); |
4544 | - if (err < 0) { |
4545 | - perror("Get interface name error"); |
4546 | - goto done; |
4547 | - } |
4548 | - |
4549 | - err = ioctl(sk, SIOCGIFHWADDR, &ifr); |
4550 | - if (err < 0) { |
4551 | - perror("Get mac address error"); |
4552 | - goto done; |
4553 | - } |
4554 | - |
4555 | - memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6); |
4556 | - |
4557 | -done: |
4558 | - close(sk); |
4559 | -} |
4560 | - |
4561 | -void g_dhcpv6_client_set_retransmit(GDHCPClient *dhcp_client) |
4562 | -{ |
4563 | - if (!dhcp_client) |
4564 | - return; |
4565 | - |
4566 | - dhcp_client->retransmit = true; |
4567 | -} |
4568 | - |
4569 | -void g_dhcpv6_client_clear_retransmit(GDHCPClient *dhcp_client) |
4570 | -{ |
4571 | - if (!dhcp_client) |
4572 | - return; |
4573 | - |
4574 | - dhcp_client->retransmit = false; |
4575 | -} |
4576 | - |
4577 | -int g_dhcpv6_create_duid(GDHCPDuidType duid_type, int index, int type, |
4578 | - unsigned char **duid, int *duid_len) |
4579 | -{ |
4580 | - time_t duid_time; |
4581 | - |
4582 | - switch (duid_type) { |
4583 | - case G_DHCPV6_DUID_LLT: |
4584 | - *duid_len = 2 + 2 + 4 + ETH_ALEN; |
4585 | - *duid = g_try_malloc(*duid_len); |
4586 | - if (!*duid) |
4587 | - return -ENOMEM; |
4588 | - |
4589 | - (*duid)[0] = 0; |
4590 | - (*duid)[1] = 1; |
4591 | - get_interface_mac_address(index, &(*duid)[2 + 2 + 4]); |
4592 | - (*duid)[2] = 0; |
4593 | - (*duid)[3] = type; |
4594 | - duid_time = time(NULL) - DUID_TIME_EPOCH; |
4595 | - (*duid)[4] = duid_time >> 24; |
4596 | - (*duid)[5] = duid_time >> 16; |
4597 | - (*duid)[6] = duid_time >> 8; |
4598 | - (*duid)[7] = duid_time & 0xff; |
4599 | - break; |
4600 | - case G_DHCPV6_DUID_EN: |
4601 | - return -EINVAL; |
4602 | - case G_DHCPV6_DUID_LL: |
4603 | - *duid_len = 2 + 2 + ETH_ALEN; |
4604 | - *duid = g_try_malloc(*duid_len); |
4605 | - if (!*duid) |
4606 | - return -ENOMEM; |
4607 | - |
4608 | - (*duid)[0] = 0; |
4609 | - (*duid)[1] = 3; |
4610 | - get_interface_mac_address(index, &(*duid)[2 + 2]); |
4611 | - (*duid)[2] = 0; |
4612 | - (*duid)[3] = type; |
4613 | - break; |
4614 | - } |
4615 | - |
4616 | - return 0; |
4617 | -} |
4618 | - |
4619 | -static gchar *convert_to_hex(unsigned char *buf, int len) |
4620 | -{ |
4621 | - gchar *ret = g_try_malloc(len * 2 + 1); |
4622 | - int i; |
4623 | - |
4624 | - for (i = 0; ret && i < len; i++) |
4625 | - g_snprintf(ret + i * 2, 3, "%02x", buf[i]); |
4626 | - |
4627 | - return ret; |
4628 | -} |
4629 | - |
4630 | -int g_dhcpv6_client_set_duid(GDHCPClient *dhcp_client, unsigned char *duid, |
4631 | - int duid_len) |
4632 | -{ |
4633 | - if (!dhcp_client || dhcp_client->type != G_DHCP_IPV6) |
4634 | - return -EINVAL; |
4635 | - |
4636 | - g_free(dhcp_client->duid); |
4637 | - |
4638 | - dhcp_client->duid = duid; |
4639 | - dhcp_client->duid_len = duid_len; |
4640 | - |
4641 | - if (dhcp_client->debug_func) { |
4642 | - gchar *hex = convert_to_hex(duid, duid_len); |
4643 | - debug(dhcp_client, "DUID(%d) %s", duid_len, hex); |
4644 | - g_free(hex); |
4645 | - } |
4646 | - |
4647 | - return 0; |
4648 | -} |
4649 | - |
4650 | -int g_dhcpv6_client_set_pd(GDHCPClient *dhcp_client, uint32_t *T1, |
4651 | - uint32_t *T2, GSList *prefixes) |
4652 | -{ |
4653 | - uint8_t options[1452]; |
4654 | - unsigned int max_buf = sizeof(options); |
4655 | - int len, count = g_slist_length(prefixes); |
4656 | - |
4657 | - if (!dhcp_client || dhcp_client->type != G_DHCP_IPV6) |
4658 | - return -EINVAL; |
4659 | - |
4660 | - g_dhcp_client_set_request(dhcp_client, G_DHCPV6_IA_PD); |
4661 | - |
4662 | - memset(options, 0, sizeof(options)); |
4663 | - |
4664 | - options[0] = dhcp_client->iaid >> 24; |
4665 | - options[1] = dhcp_client->iaid >> 16; |
4666 | - options[2] = dhcp_client->iaid >> 8; |
4667 | - options[3] = dhcp_client->iaid; |
4668 | - |
4669 | - if (T1) { |
4670 | - uint32_t t = htonl(*T1); |
4671 | - memcpy(&options[4], &t, 4); |
4672 | - } |
4673 | - |
4674 | - if (T2) { |
4675 | - uint32_t t = htonl(*T2); |
4676 | - memcpy(&options[8], &t, 4); |
4677 | - } |
4678 | - |
4679 | - len = 12; |
4680 | - |
4681 | - if (count > 0) { |
4682 | - GSList *list; |
4683 | - |
4684 | - for (list = prefixes; list; list = list->next) { |
4685 | - GDHCPIAPrefix *prefix = list->data; |
4686 | - uint8_t sub_option[4+4+1+16]; |
4687 | - |
4688 | - if ((len + 2 + 2 + sizeof(sub_option)) >= max_buf) { |
4689 | - debug(dhcp_client, |
4690 | - "Too long dhcpv6 message " |
4691 | - "when writing IA prefix option"); |
4692 | - return -EINVAL; |
4693 | - } |
4694 | - |
4695 | - memset(&sub_option, 0, sizeof(sub_option)); |
4696 | - |
4697 | - /* preferred and validity time are left zero */ |
4698 | - |
4699 | - sub_option[8] = prefix->prefixlen; |
4700 | - memcpy(&sub_option[9], &prefix->prefix, 16); |
4701 | - |
4702 | - copy_option(&options[len], G_DHCPV6_IA_PREFIX, |
4703 | - sizeof(sub_option), sub_option); |
4704 | - len += 2 + 2 + sizeof(sub_option); |
4705 | - } |
4706 | - } |
4707 | - |
4708 | - g_dhcpv6_client_set_send(dhcp_client, G_DHCPV6_IA_PD, |
4709 | - options, len); |
4710 | - |
4711 | - return 0; |
4712 | -} |
4713 | - |
4714 | -uint32_t g_dhcpv6_client_get_iaid(GDHCPClient *dhcp_client) |
4715 | -{ |
4716 | - if (!dhcp_client || dhcp_client->type != G_DHCP_IPV6) |
4717 | - return 0; |
4718 | - |
4719 | - return dhcp_client->iaid; |
4720 | -} |
4721 | - |
4722 | -void g_dhcpv6_client_set_iaid(GDHCPClient *dhcp_client, uint32_t iaid) |
4723 | -{ |
4724 | - if (!dhcp_client || dhcp_client->type != G_DHCP_IPV6) |
4725 | - return; |
4726 | - |
4727 | - dhcp_client->iaid = iaid; |
4728 | -} |
4729 | - |
4730 | -void g_dhcpv6_client_create_iaid(GDHCPClient *dhcp_client, int index, |
4731 | - unsigned char *iaid) |
4732 | -{ |
4733 | - uint8_t buf[6] = { }; |
4734 | - |
4735 | - get_interface_mac_address(index, buf); |
4736 | - |
4737 | - memcpy(iaid, &buf[2], 4); |
4738 | - dhcp_client->iaid = iaid[0] << 24 | |
4739 | - iaid[1] << 16 | iaid[2] << 8 | iaid[3]; |
4740 | -} |
4741 | - |
4742 | -int g_dhcpv6_client_get_timeouts(GDHCPClient *dhcp_client, |
4743 | - uint32_t *T1, uint32_t *T2, |
4744 | - time_t *started, |
4745 | - time_t *expire) |
4746 | -{ |
4747 | - if (!dhcp_client || dhcp_client->type != G_DHCP_IPV6) |
4748 | - return -EINVAL; |
4749 | - |
4750 | - if (T1) |
4751 | - *T1 = dhcp_client->T1; |
4752 | - |
4753 | - if (T2) |
4754 | - *T2 = dhcp_client->T2; |
4755 | - |
4756 | - if (started) |
4757 | - *started = dhcp_client->last_request; |
4758 | - |
4759 | - if (expire) |
4760 | - *expire = dhcp_client->last_request + dhcp_client->expire; |
4761 | - |
4762 | - return 0; |
4763 | -} |
4764 | - |
4765 | -static uint8_t *create_iaaddr(GDHCPClient *dhcp_client, uint8_t *buf, |
4766 | - uint16_t len) |
4767 | -{ |
4768 | - buf[0] = 0; |
4769 | - buf[1] = G_DHCPV6_IAADDR; |
4770 | - buf[2] = 0; |
4771 | - buf[3] = len; |
4772 | - memcpy(&buf[4], &dhcp_client->ia_na, 16); |
4773 | - memset(&buf[20], 0, 4); /* preferred */ |
4774 | - memset(&buf[24], 0, 4); /* valid */ |
4775 | - return buf; |
4776 | -} |
4777 | - |
4778 | -static uint8_t *append_iaaddr(GDHCPClient *dhcp_client, uint8_t *buf, |
4779 | - const char *address) |
4780 | -{ |
4781 | - struct in6_addr addr; |
4782 | - |
4783 | - if (inet_pton(AF_INET6, address, &addr) != 1) |
4784 | - return NULL; |
4785 | - |
4786 | - buf[0] = 0; |
4787 | - buf[1] = G_DHCPV6_IAADDR; |
4788 | - buf[2] = 0; |
4789 | - buf[3] = 24; |
4790 | - memcpy(&buf[4], &addr, 16); |
4791 | - memset(&buf[20], 0, 4); /* preferred */ |
4792 | - memset(&buf[24], 0, 4); /* valid */ |
4793 | - return &buf[28]; |
4794 | -} |
4795 | - |
4796 | -static void put_iaid(GDHCPClient *dhcp_client, int index, uint8_t *buf) |
4797 | -{ |
4798 | - uint32_t iaid; |
4799 | - |
4800 | - iaid = g_dhcpv6_client_get_iaid(dhcp_client); |
4801 | - if (iaid == 0) { |
4802 | - g_dhcpv6_client_create_iaid(dhcp_client, index, buf); |
4803 | - return; |
4804 | - } |
4805 | - |
4806 | - buf[0] = iaid >> 24; |
4807 | - buf[1] = iaid >> 16; |
4808 | - buf[2] = iaid >> 8; |
4809 | - buf[3] = iaid; |
4810 | -} |
4811 | - |
4812 | -int g_dhcpv6_client_set_ia(GDHCPClient *dhcp_client, int index, |
4813 | - int code, uint32_t *T1, uint32_t *T2, |
4814 | - bool add_iaaddr, const char *ia_na) |
4815 | -{ |
4816 | - if (code == G_DHCPV6_IA_TA) { |
4817 | - uint8_t ia_options[4]; |
4818 | - |
4819 | - put_iaid(dhcp_client, index, ia_options); |
4820 | - |
4821 | - g_dhcp_client_set_request(dhcp_client, G_DHCPV6_IA_TA); |
4822 | - g_dhcpv6_client_set_send(dhcp_client, G_DHCPV6_IA_TA, |
4823 | - ia_options, sizeof(ia_options)); |
4824 | - |
4825 | - } else if (code == G_DHCPV6_IA_NA) { |
4826 | - struct in6_addr addr; |
4827 | - |
4828 | - g_dhcp_client_set_request(dhcp_client, G_DHCPV6_IA_NA); |
4829 | - |
4830 | - /* |
4831 | - * If caller has specified the IPv6 address it wishes to |
4832 | - * to use (ia_na != NULL and address is valid), then send |
4833 | - * the address to server. |
4834 | - * If caller did not specify the address (ia_na == NULL) and |
4835 | - * if the current address is not set, then we should not send |
4836 | - * the address sub-option. |
4837 | - */ |
4838 | - if (add_iaaddr && ((!ia_na && |
4839 | - !IN6_IS_ADDR_UNSPECIFIED(&dhcp_client->ia_na)) |
4840 | - || (ia_na && |
4841 | - inet_pton(AF_INET6, ia_na, &addr) == 1))) { |
4842 | -#define IAADDR_LEN (16+4+4) |
4843 | - uint8_t ia_options[4+4+4+2+2+IAADDR_LEN]; |
4844 | - |
4845 | - if (ia_na) |
4846 | - memcpy(&dhcp_client->ia_na, &addr, |
4847 | - sizeof(struct in6_addr)); |
4848 | - |
4849 | - put_iaid(dhcp_client, index, ia_options); |
4850 | - |
4851 | - if (T1) { |
4852 | - ia_options[4] = *T1 >> 24; |
4853 | - ia_options[5] = *T1 >> 16; |
4854 | - ia_options[6] = *T1 >> 8; |
4855 | - ia_options[7] = *T1; |
4856 | - } else |
4857 | - memset(&ia_options[4], 0x00, 4); |
4858 | - |
4859 | - if (T2) { |
4860 | - ia_options[8] = *T2 >> 24; |
4861 | - ia_options[9] = *T2 >> 16; |
4862 | - ia_options[10] = *T2 >> 8; |
4863 | - ia_options[11] = *T2; |
4864 | - } else |
4865 | - memset(&ia_options[8], 0x00, 4); |
4866 | - |
4867 | - create_iaaddr(dhcp_client, &ia_options[12], |
4868 | - IAADDR_LEN); |
4869 | - |
4870 | - g_dhcpv6_client_set_send(dhcp_client, G_DHCPV6_IA_NA, |
4871 | - ia_options, sizeof(ia_options)); |
4872 | - } else { |
4873 | - uint8_t ia_options[4+4+4]; |
4874 | - |
4875 | - put_iaid(dhcp_client, index, ia_options); |
4876 | - |
4877 | - memset(&ia_options[4], 0x00, 4); /* T1 (4 bytes) */ |
4878 | - memset(&ia_options[8], 0x00, 4); /* T2 (4 bytes) */ |
4879 | - |
4880 | - g_dhcpv6_client_set_send(dhcp_client, G_DHCPV6_IA_NA, |
4881 | - ia_options, sizeof(ia_options)); |
4882 | - } |
4883 | - |
4884 | - } else |
4885 | - return -EINVAL; |
4886 | - |
4887 | - return 0; |
4888 | -} |
4889 | - |
4890 | -int g_dhcpv6_client_set_ias(GDHCPClient *dhcp_client, int index, |
4891 | - int code, uint32_t *T1, uint32_t *T2, |
4892 | - GSList *addresses) |
4893 | -{ |
4894 | - GSList *list; |
4895 | - uint8_t *ia_options, *pos; |
4896 | - int len, count, total_len; |
4897 | - |
4898 | - count = g_slist_length(addresses); |
4899 | - if (count == 0) |
4900 | - return -EINVAL; |
4901 | - |
4902 | - g_dhcp_client_set_request(dhcp_client, code); |
4903 | - |
4904 | - if (code == G_DHCPV6_IA_TA) |
4905 | - len = 4; /* IAID */ |
4906 | - else if (code == G_DHCPV6_IA_NA) |
4907 | - len = 4 + 4 + 4; /* IAID + T1 + T2 */ |
4908 | - else |
4909 | - return -EINVAL; |
4910 | - |
4911 | - total_len = len + count * (2 + 2 + 16 + 4 + 4); |
4912 | - ia_options = g_try_malloc0(total_len); |
4913 | - if (!ia_options) |
4914 | - return -ENOMEM; |
4915 | - |
4916 | - put_iaid(dhcp_client, index, ia_options); |
4917 | - |
4918 | - pos = &ia_options[len]; /* skip the IA_NA or IA_TA */ |
4919 | - |
4920 | - for (list = addresses; list; list = list->next) { |
4921 | - pos = append_iaaddr(dhcp_client, pos, list->data); |
4922 | - if (!pos) |
4923 | - break; |
4924 | - } |
4925 | - |
4926 | - if (code == G_DHCPV6_IA_NA) { |
4927 | - if (T1) { |
4928 | - ia_options[4] = *T1 >> 24; |
4929 | - ia_options[5] = *T1 >> 16; |
4930 | - ia_options[6] = *T1 >> 8; |
4931 | - ia_options[7] = *T1; |
4932 | - } else |
4933 | - memset(&ia_options[4], 0x00, 4); |
4934 | - |
4935 | - if (T2) { |
4936 | - ia_options[8] = *T2 >> 24; |
4937 | - ia_options[9] = *T2 >> 16; |
4938 | - ia_options[10] = *T2 >> 8; |
4939 | - ia_options[11] = *T2; |
4940 | - } else |
4941 | - memset(&ia_options[8], 0x00, 4); |
4942 | - } |
4943 | - |
4944 | - g_dhcpv6_client_set_send(dhcp_client, code, ia_options, total_len); |
4945 | - |
4946 | - g_free(ia_options); |
4947 | - |
4948 | - return 0; |
4949 | -} |
4950 | - |
4951 | -int g_dhcpv6_client_set_oro(GDHCPClient *dhcp_client, int args, ...) |
4952 | -{ |
4953 | - va_list va; |
4954 | - int i, j, len = sizeof(uint16_t) * args; |
4955 | - uint8_t *values; |
4956 | - |
4957 | - values = g_try_malloc(len); |
4958 | - if (!values) |
4959 | - return -ENOMEM; |
4960 | - |
4961 | - va_start(va, args); |
4962 | - for (i = 0, j = 0; i < args; i++) { |
4963 | - uint16_t value = va_arg(va, int); |
4964 | - values[j++] = value >> 8; |
4965 | - values[j++] = value & 0xff; |
4966 | - } |
4967 | - va_end(va); |
4968 | - |
4969 | - g_dhcpv6_client_set_send(dhcp_client, G_DHCPV6_ORO, values, len); |
4970 | - |
4971 | - g_free(values); |
4972 | - |
4973 | - return 0; |
4974 | -} |
4975 | - |
4976 | -static int send_dhcpv6_msg(GDHCPClient *dhcp_client, int type, char *msg) |
4977 | -{ |
4978 | - struct dhcpv6_packet *packet; |
4979 | - uint8_t buf[MAX_DHCPV6_PKT_SIZE]; |
4980 | - unsigned char *ptr; |
4981 | - int ret, max_buf; |
4982 | - |
4983 | - memset(buf, 0, sizeof(buf)); |
4984 | - packet = (struct dhcpv6_packet *)&buf[0]; |
4985 | - ptr = buf + sizeof(struct dhcpv6_packet); |
4986 | - |
4987 | - init_packet(dhcp_client, packet, type); |
4988 | - |
4989 | - if (!dhcp_client->retransmit) { |
4990 | - dhcp_client->xid = packet->transaction_id[0] << 16 | |
4991 | - packet->transaction_id[1] << 8 | |
4992 | - packet->transaction_id[2]; |
4993 | - gettimeofday(&dhcp_client->start_time, NULL); |
4994 | - } else { |
4995 | - packet->transaction_id[0] = dhcp_client->xid >> 16; |
4996 | - packet->transaction_id[1] = dhcp_client->xid >> 8 ; |
4997 | - packet->transaction_id[2] = dhcp_client->xid; |
4998 | - } |
4999 | - |
5000 | - g_dhcp_client_set_request(dhcp_client, G_DHCPV6_ELAPSED_TIME); |