mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge mozilla-inbound to mozilla-central
This commit is contained in:
commit
9325b1542c
@ -1036,6 +1036,7 @@ var gBrowserInit = {
|
||||
gFormSubmitObserver.init();
|
||||
SocialUI.init();
|
||||
gRemoteTabsUI.init();
|
||||
gPageStyleMenu.init();
|
||||
|
||||
// Initialize the full zoom setting.
|
||||
// We do this before the session restore service gets initialized so we can
|
||||
@ -1092,12 +1093,9 @@ var gBrowserInit = {
|
||||
if (!getBoolPref("ui.click_hold_context_menus", false))
|
||||
SetClickAndHoldHandlers();
|
||||
|
||||
// Bug 666804 - NetworkPrioritizer support for e10s
|
||||
if (!gMultiProcessBrowser) {
|
||||
let NP = {};
|
||||
Cu.import("resource:///modules/NetworkPrioritizer.jsm", NP);
|
||||
NP.trackBrowserWindow(window);
|
||||
}
|
||||
let NP = {};
|
||||
Cu.import("resource:///modules/NetworkPrioritizer.jsm", NP);
|
||||
NP.trackBrowserWindow(window);
|
||||
|
||||
PlacesToolbarHelper.init();
|
||||
|
||||
@ -3497,15 +3495,17 @@ var XULBrowserWindow = {
|
||||
const nsIWebProgressListener = Ci.nsIWebProgressListener;
|
||||
const nsIChannel = Ci.nsIChannel;
|
||||
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
if (aStateFlags & nsIWebProgressListener.STATE_START &&
|
||||
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
|
||||
|
||||
if (aRequest && aWebProgress.isTopLevel) {
|
||||
// clear out feed data
|
||||
gBrowser.selectedBrowser.feeds = null;
|
||||
browser.feeds = null;
|
||||
|
||||
// clear out search-engine data
|
||||
gBrowser.selectedBrowser.engines = null;
|
||||
browser.engines = null;
|
||||
}
|
||||
|
||||
this.isBusy = true;
|
||||
@ -3546,7 +3546,7 @@ var XULBrowserWindow = {
|
||||
this.setDefaultStatus(msg);
|
||||
|
||||
// Disable menu entries for images, enable otherwise
|
||||
if (!gMultiProcessBrowser && content.document && mimeTypeIsTextBased(content.document.contentType))
|
||||
if (browser.documentContentType && mimeTypeIsTextBased(browser.documentContentType))
|
||||
this.isImage.removeAttribute('disabled');
|
||||
else
|
||||
this.isImage.setAttribute('disabled', 'true');
|
||||
@ -3590,8 +3590,10 @@ var XULBrowserWindow = {
|
||||
}
|
||||
}
|
||||
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
// Disable menu entries for images, enable otherwise
|
||||
if (!gMultiProcessBrowser && content.document && mimeTypeIsTextBased(content.document.contentType))
|
||||
if (browser.documentContentType && mimeTypeIsTextBased(browser.documentContentType))
|
||||
this.isImage.removeAttribute('disabled');
|
||||
else
|
||||
this.isImage.setAttribute('disabled', 'true');
|
||||
@ -3605,7 +3607,6 @@ var XULBrowserWindow = {
|
||||
// Update urlbar only if a new page was loaded on the primary content area
|
||||
// Do not update urlbar if there was a subframe navigation
|
||||
|
||||
var browser = gBrowser.selectedBrowser;
|
||||
if (aWebProgress.isTopLevel) {
|
||||
if ((location == "about:blank" && (gMultiProcessBrowser || !content.opener)) ||
|
||||
location == "") { // Second condition is for new tabs, otherwise
|
||||
@ -5199,39 +5200,54 @@ function charsetLoadListener() {
|
||||
|
||||
var gPageStyleMenu = {
|
||||
|
||||
_getAllStyleSheets: function (frameset) {
|
||||
var styleSheetsArray = Array.slice(frameset.document.styleSheets);
|
||||
for (let i = 0; i < frameset.frames.length; i++) {
|
||||
let frameSheets = this._getAllStyleSheets(frameset.frames[i]);
|
||||
styleSheetsArray = styleSheetsArray.concat(frameSheets);
|
||||
// This maps from a <browser> element (or, more specifically, a
|
||||
// browser's permanentKey) to a CPOW that gives synchronous access
|
||||
// to the list of style sheets in a content window. The use of the
|
||||
// permanentKey is to avoid issues with docshell swapping.
|
||||
_pageStyleSyncHandlers: new WeakMap(),
|
||||
|
||||
init: function() {
|
||||
let mm = window.messageManager;
|
||||
mm.addMessageListener("PageStyle:SetSyncHandler", (msg) => {
|
||||
this._pageStyleSyncHandlers.set(msg.target.permanentKey, msg.objects.syncHandler);
|
||||
});
|
||||
},
|
||||
|
||||
getAllStyleSheets: function () {
|
||||
let handler = this._pageStyleSyncHandlers.get(gBrowser.selectedBrowser.permanentKey);
|
||||
try {
|
||||
return handler.getAllStyleSheets();
|
||||
} catch (ex) {
|
||||
// In case the child died or timed out.
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
_getStyleSheetInfo: function (browser) {
|
||||
let handler = this._pageStyleSyncHandlers.get(gBrowser.selectedBrowser.permanentKey);
|
||||
try {
|
||||
return handler.getStyleSheetInfo();
|
||||
} catch (ex) {
|
||||
// In case the child died or timed out.
|
||||
return {styleSheets: [], authorStyleDisabled: false, preferredStyleSheetSet: true};
|
||||
}
|
||||
return styleSheetsArray;
|
||||
},
|
||||
|
||||
fillPopup: function (menuPopup) {
|
||||
let styleSheetInfo = this._getStyleSheetInfo(gBrowser.selectedBrowser);
|
||||
var noStyle = menuPopup.firstChild;
|
||||
var persistentOnly = noStyle.nextSibling;
|
||||
var sep = persistentOnly.nextSibling;
|
||||
while (sep.nextSibling)
|
||||
menuPopup.removeChild(sep.nextSibling);
|
||||
|
||||
var styleSheets = this._getAllStyleSheets(window.content);
|
||||
let styleSheets = styleSheetInfo.styleSheets;
|
||||
var currentStyleSheets = {};
|
||||
var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled;
|
||||
var styleDisabled = styleSheetInfo.authorStyleDisabled;
|
||||
var haveAltSheets = false;
|
||||
var altStyleSelected = false;
|
||||
|
||||
for (let currentStyleSheet of styleSheets) {
|
||||
if (!currentStyleSheet.title)
|
||||
continue;
|
||||
|
||||
// Skip any stylesheets whose media attribute doesn't match.
|
||||
if (currentStyleSheet.media.length > 0) {
|
||||
let mediaQueryList = currentStyleSheet.media.mediaText;
|
||||
if (!window.content.matchMedia(mediaQueryList).matches)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!currentStyleSheet.disabled)
|
||||
altStyleSelected = true;
|
||||
|
||||
@ -5257,51 +5273,29 @@ var gPageStyleMenu = {
|
||||
|
||||
noStyle.setAttribute("checked", styleDisabled);
|
||||
persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled);
|
||||
persistentOnly.hidden = (window.content.document.preferredStyleSheetSet) ? haveAltSheets : false;
|
||||
persistentOnly.hidden = styleSheetInfo.preferredStyleSheetSet ? haveAltSheets : false;
|
||||
sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
|
||||
},
|
||||
|
||||
_stylesheetInFrame: function (frame, title) {
|
||||
return Array.some(frame.document.styleSheets,
|
||||
function (stylesheet) stylesheet.title == title);
|
||||
},
|
||||
|
||||
_stylesheetSwitchFrame: function (frame, title) {
|
||||
var docStyleSheets = frame.document.styleSheets;
|
||||
|
||||
for (let i = 0; i < docStyleSheets.length; ++i) {
|
||||
let docStyleSheet = docStyleSheets[i];
|
||||
|
||||
if (docStyleSheet.title)
|
||||
docStyleSheet.disabled = (docStyleSheet.title != title);
|
||||
else if (docStyleSheet.disabled)
|
||||
docStyleSheet.disabled = false;
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetSwitchAll: function (frameset, title) {
|
||||
if (!title || this._stylesheetInFrame(frameset, title))
|
||||
this._stylesheetSwitchFrame(frameset, title);
|
||||
|
||||
for (let i = 0; i < frameset.frames.length; i++)
|
||||
this._stylesheetSwitchAll(frameset.frames[i], title);
|
||||
},
|
||||
|
||||
switchStyleSheet: function (title, contentWindow) {
|
||||
getMarkupDocumentViewer().authorStyleDisabled = false;
|
||||
this._stylesheetSwitchAll(contentWindow || content, title);
|
||||
switchStyleSheet: function (title) {
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
mm.sendAsyncMessage("PageStyle:Switch", {title: title});
|
||||
},
|
||||
|
||||
disableStyle: function () {
|
||||
getMarkupDocumentViewer().authorStyleDisabled = true;
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
mm.sendAsyncMessage("PageStyle:Disable");
|
||||
},
|
||||
};
|
||||
|
||||
/* Legacy global page-style functions */
|
||||
var getAllStyleSheets = gPageStyleMenu._getAllStyleSheets.bind(gPageStyleMenu);
|
||||
var getAllStyleSheets = gPageStyleMenu.getAllStyleSheets.bind(gPageStyleMenu);
|
||||
var stylesheetFillPopup = gPageStyleMenu.fillPopup.bind(gPageStyleMenu);
|
||||
function stylesheetSwitchAll(contentWindow, title) {
|
||||
gPageStyleMenu.switchStyleSheet(title, contentWindow);
|
||||
// We ignore the contentWindow param. Add-ons don't appear to use
|
||||
// it, and it's difficult to support in e10s (where it will be a
|
||||
// CPOW).
|
||||
gPageStyleMenu.switchStyleSheet(title);
|
||||
}
|
||||
function setStyleDisabled(disabled) {
|
||||
if (disabled)
|
||||
|
@ -290,3 +290,99 @@ ContentLinkHandler.init(this);
|
||||
addEventListener("DOMWebNotificationClicked", function(event) {
|
||||
sendAsyncMessage("DOMWebNotificationClicked", {});
|
||||
}, false);
|
||||
|
||||
let PageStyleHandler = {
|
||||
init: function() {
|
||||
addMessageListener("PageStyle:Switch", this);
|
||||
addMessageListener("PageStyle:Disable", this);
|
||||
|
||||
// Send a CPOW to the parent so that it can synchronously request
|
||||
// the list of style sheets.
|
||||
sendSyncMessage("PageStyle:SetSyncHandler", {}, {syncHandler: this});
|
||||
},
|
||||
|
||||
get markupDocumentViewer() {
|
||||
return docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
|
||||
},
|
||||
|
||||
// Called synchronously via CPOW from the parent.
|
||||
getStyleSheetInfo: function() {
|
||||
let styleSheets = this._filterStyleSheets(this.getAllStyleSheets());
|
||||
return {
|
||||
styleSheets: styleSheets,
|
||||
authorStyleDisabled: this.markupDocumentViewer.authorStyleDisabled,
|
||||
preferredStyleSheetSet: content.document.preferredStyleSheetSet
|
||||
};
|
||||
},
|
||||
|
||||
// Called synchronously via CPOW from the parent.
|
||||
getAllStyleSheets: function(frameset = content) {
|
||||
let selfSheets = Array.slice(frameset.document.styleSheets);
|
||||
let subSheets = Array.map(frameset.frames, frame => this.getAllStyleSheets(frame));
|
||||
return selfSheets.concat(...subSheets);
|
||||
},
|
||||
|
||||
receiveMessage: function(msg) {
|
||||
switch (msg.name) {
|
||||
case "PageStyle:Switch":
|
||||
this.markupDocumentViewer.authorStyleDisabled = false;
|
||||
this._stylesheetSwitchAll(content, msg.data.title);
|
||||
break;
|
||||
|
||||
case "PageStyle:Disable":
|
||||
this.markupDocumentViewer.authorStyleDisabled = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetSwitchAll: function (frameset, title) {
|
||||
if (!title || this._stylesheetInFrame(frameset, title)) {
|
||||
this._stylesheetSwitchFrame(frameset, title);
|
||||
}
|
||||
|
||||
for (let i = 0; i < frameset.frames.length; i++) {
|
||||
// Recurse into sub-frames.
|
||||
this._stylesheetSwitchAll(frameset.frames[i], title);
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetSwitchFrame: function (frame, title) {
|
||||
var docStyleSheets = frame.document.styleSheets;
|
||||
|
||||
for (let i = 0; i < docStyleSheets.length; ++i) {
|
||||
let docStyleSheet = docStyleSheets[i];
|
||||
if (docStyleSheet.title) {
|
||||
docStyleSheet.disabled = (docStyleSheet.title != title);
|
||||
} else if (docStyleSheet.disabled) {
|
||||
docStyleSheet.disabled = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_stylesheetInFrame: function (frame, title) {
|
||||
return Array.some(frame.document.styleSheets, (styleSheet) => styleSheet.title == title);
|
||||
},
|
||||
|
||||
_filterStyleSheets: function(styleSheets) {
|
||||
let result = [];
|
||||
|
||||
for (let currentStyleSheet of styleSheets) {
|
||||
if (!currentStyleSheet.title)
|
||||
continue;
|
||||
|
||||
// Skip any stylesheets that don't match the screen media type.
|
||||
if (currentStyleSheet.media.length > 0) {
|
||||
let mediaQueryList = currentStyleSheet.media.mediaText;
|
||||
if (!content.matchMedia(mediaQueryList).matches) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.push({title: currentStyleSheet.title,
|
||||
disabled: currentStyleSheet.disabled});
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
||||
PageStyleHandler.init();
|
||||
|
@ -80,18 +80,12 @@ let BrowserHelper = {
|
||||
windowEntry.lastSelectedBrowser = aBrowser;
|
||||
},
|
||||
|
||||
// Auxiliary methods
|
||||
getLoadgroup: function NP_BH_getLoadgroup(aBrowser) {
|
||||
return aBrowser.webNavigation.QueryInterface(Ci.nsIDocumentLoader)
|
||||
.loadGroup.QueryInterface(Ci.nsISupportsPriority);
|
||||
},
|
||||
|
||||
increasePriority: function NP_BH_increasePriority(aBrowser) {
|
||||
this.getLoadgroup(aBrowser).adjustPriority(PRIORITY_DELTA);
|
||||
aBrowser.adjustPriority(PRIORITY_DELTA);
|
||||
},
|
||||
|
||||
decreasePriority: function NP_BH_decreasePriority(aBrowser) {
|
||||
this.getLoadgroup(aBrowser).adjustPriority(PRIORITY_DELTA * -1);
|
||||
aBrowser.adjustPriority(PRIORITY_DELTA * -1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -105,7 +105,7 @@ class MachCommands(MachCommandBase):
|
||||
'--smc-check=all-non-file',
|
||||
'--vex-iropt-register-updates=allregs-at-mem-access',
|
||||
'--gen-suppressions=all',
|
||||
'--num-callers=20',
|
||||
'--num-callers=36',
|
||||
'--leak-check=full',
|
||||
'--show-possibly-lost=no',
|
||||
'--track-origins=yes'
|
||||
|
@ -96,6 +96,17 @@ WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex, GLenum target, GLin
|
||||
mRenderbufferPtr = nullptr;
|
||||
mTexImageTarget = target;
|
||||
mTexImageLevel = level;
|
||||
|
||||
mNeedsFinalize = true;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::Attachment::SetRenderbuffer(WebGLRenderbuffer* rb)
|
||||
{
|
||||
mTexturePtr = nullptr;
|
||||
mRenderbufferPtr = rb;
|
||||
|
||||
mNeedsFinalize = true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -315,12 +326,31 @@ WebGLFramebuffer::Attachment::IsComplete() const
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::Attachment::FinalizeAttachment(GLenum attachmentLoc) const
|
||||
WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, GLenum attachmentLoc) const
|
||||
{
|
||||
if (!mNeedsFinalize)
|
||||
return;
|
||||
|
||||
mNeedsFinalize = false;
|
||||
|
||||
if (!HasImage()) {
|
||||
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER, 0);
|
||||
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER, 0);
|
||||
} else {
|
||||
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachmentLoc,
|
||||
LOCAL_GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(HasImage());
|
||||
|
||||
if (Texture()) {
|
||||
GLContext* gl = Texture()->Context()->gl;
|
||||
MOZ_ASSERT(gl == Texture()->Context()->gl);
|
||||
|
||||
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
TexImageTarget(), Texture()->GLName(), TexImageLevel());
|
||||
@ -832,22 +862,18 @@ FinalizeDrawAndReadBuffers(GLContext* aGL, bool aColorBufferDefined)
|
||||
void
|
||||
WebGLFramebuffer::FinalizeAttachments() const
|
||||
{
|
||||
GLContext* gl = mContext->gl;
|
||||
|
||||
size_t count = ColorAttachmentCount();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (ColorAttachment(i).IsDefined())
|
||||
ColorAttachment(i).FinalizeAttachment(LOCAL_GL_COLOR_ATTACHMENT0 + i);
|
||||
ColorAttachment(i).FinalizeAttachment(gl, LOCAL_GL_COLOR_ATTACHMENT0 + i);
|
||||
}
|
||||
|
||||
if (DepthAttachment().IsDefined())
|
||||
DepthAttachment().FinalizeAttachment(LOCAL_GL_DEPTH_ATTACHMENT);
|
||||
DepthAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_ATTACHMENT);
|
||||
StencilAttachment().FinalizeAttachment(gl, LOCAL_GL_STENCIL_ATTACHMENT);
|
||||
DepthStencilAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
|
||||
|
||||
if (StencilAttachment().IsDefined())
|
||||
StencilAttachment().FinalizeAttachment(LOCAL_GL_STENCIL_ATTACHMENT);
|
||||
|
||||
if (DepthStencilAttachment().IsDefined())
|
||||
DepthStencilAttachment().FinalizeAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
|
||||
|
||||
FinalizeDrawAndReadBuffers(mContext->gl, ColorAttachment(0).IsDefined());
|
||||
FinalizeDrawAndReadBuffers(gl, ColorAttachment(0).IsDefined());
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -41,9 +41,11 @@ public:
|
||||
GLenum mAttachmentPoint;
|
||||
GLenum mTexImageTarget;
|
||||
GLint mTexImageLevel;
|
||||
mutable bool mNeedsFinalize;
|
||||
|
||||
Attachment(GLenum aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
: mAttachmentPoint(aAttachmentPoint)
|
||||
, mNeedsFinalize(false)
|
||||
{}
|
||||
|
||||
bool IsDefined() const {
|
||||
@ -56,10 +58,8 @@ public:
|
||||
bool IsReadableFloat() const;
|
||||
|
||||
void SetTexImage(WebGLTexture* tex, GLenum target, GLint level);
|
||||
void SetRenderbuffer(WebGLRenderbuffer* rb) {
|
||||
mTexturePtr = nullptr;
|
||||
mRenderbufferPtr = rb;
|
||||
}
|
||||
void SetRenderbuffer(WebGLRenderbuffer* rb);
|
||||
|
||||
const WebGLTexture* Texture() const {
|
||||
return mTexturePtr;
|
||||
}
|
||||
@ -92,7 +92,7 @@ public:
|
||||
bool HasImage() const;
|
||||
bool IsComplete() const;
|
||||
|
||||
void FinalizeAttachment(GLenum attachmentLoc) const;
|
||||
void FinalizeAttachment(gl::GLContext* gl, GLenum attachmentLoc) const;
|
||||
};
|
||||
|
||||
void Delete();
|
||||
|
@ -142,6 +142,24 @@ public:
|
||||
return mContentType;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
// Not owned:
|
||||
// - mBuffer
|
||||
// - mPrincipal
|
||||
size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mContentType.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t * mBuffer;
|
||||
uint32_t mLength;
|
||||
|
@ -386,6 +386,28 @@ MediaCacheStream::MediaCacheStream(ChannelMediaResource* aClient)
|
||||
{
|
||||
}
|
||||
|
||||
size_t MediaCacheStream::SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
// Looks like these are not owned:
|
||||
// - mClient
|
||||
// - mPrincipal
|
||||
size_t size = mBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mReadaheadBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mMetadataBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mPlayedBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mPartialBlockBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t MediaCacheStream::BlockList::SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mEntries.SizeOfExcludingThis(/* sizeOfEntryExcludingThis = */ nullptr,
|
||||
aMallocSizeOf);
|
||||
}
|
||||
|
||||
void MediaCacheStream::BlockList::AddFirstBlock(int32_t aBlock)
|
||||
{
|
||||
NS_ASSERTION(!mEntries.GetEntry(aBlock), "Block already in list");
|
||||
|
@ -342,6 +342,9 @@ public:
|
||||
// 'Read' for argument and return details.
|
||||
nsresult ReadAt(int64_t aOffset, char* aBuffer,
|
||||
uint32_t aCount, uint32_t* aBytes);
|
||||
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
private:
|
||||
friend class MediaCache;
|
||||
|
||||
@ -385,6 +388,8 @@ private:
|
||||
void Verify() {}
|
||||
#endif
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
private:
|
||||
struct Entry : public nsUint32HashKey {
|
||||
Entry(KeyTypePointer aKey) : nsUint32HashKey(aKey) { }
|
||||
|
@ -59,6 +59,8 @@ class MediaMemoryTracker : public nsIMemoryReporter
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIMEMORYREPORTER
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
|
||||
|
||||
MediaMemoryTracker();
|
||||
virtual ~MediaMemoryTracker();
|
||||
void InitMemoryReporter();
|
||||
@ -1830,10 +1832,16 @@ MediaMemoryTracker::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData)
|
||||
{
|
||||
int64_t video = 0, audio = 0;
|
||||
size_t resources = 0;
|
||||
DecodersArray& decoders = Decoders();
|
||||
for (size_t i = 0; i < decoders.Length(); ++i) {
|
||||
video += decoders[i]->VideoQueueMemoryInUse();
|
||||
audio += decoders[i]->SizeOfAudioQueue();
|
||||
MediaDecoder* decoder = decoders[i];
|
||||
video += decoder->VideoQueueMemoryInUse();
|
||||
audio += decoder->SizeOfAudioQueue();
|
||||
|
||||
if (decoder->GetResource()) {
|
||||
resources += decoder->GetResource()->SizeOfIncludingThis(MallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
#define REPORT(_path, _amount, _desc) \
|
||||
@ -1845,12 +1853,16 @@ MediaMemoryTracker::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
} while (0)
|
||||
|
||||
REPORT("explicit/media/decoded-video", video,
|
||||
REPORT("explicit/media/decoded/video", video,
|
||||
"Memory used by decoded video frames.");
|
||||
|
||||
REPORT("explicit/media/decoded-audio", audio,
|
||||
REPORT("explicit/media/decoded/audio", audio,
|
||||
"Memory used by decoded audio chunks.");
|
||||
|
||||
REPORT("explicit/media/resources", resources,
|
||||
"Memory used by media resources including streaming buffers, caches, "
|
||||
"etc.");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1248,6 +1248,20 @@ public:
|
||||
|
||||
nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges);
|
||||
|
||||
virtual size_t SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
// Might be useful to track in the future:
|
||||
// - mInput
|
||||
return BaseMediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
protected:
|
||||
// These Unsafe variants of Read and Seek perform their operations
|
||||
// without acquiring mLock. The caller must obtain the lock before
|
||||
|
@ -393,6 +393,14 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~MediaResource() {};
|
||||
|
||||
@ -405,6 +413,26 @@ public:
|
||||
virtual nsIURI* URI() const { return mURI; }
|
||||
virtual void MoveLoadsToBackground();
|
||||
|
||||
virtual size_t SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
// Might be useful to track in the future:
|
||||
// - mChannel
|
||||
// - mURI (possibly owned, looks like just a ref from mChannel)
|
||||
// Not owned:
|
||||
// - mDecoder
|
||||
size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mContentType.SizeOfIncludingThisIfUnshared(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
protected:
|
||||
BaseMediaResource(MediaDecoder* aDecoder,
|
||||
nsIChannel* aChannel,
|
||||
@ -556,6 +584,24 @@ public:
|
||||
virtual bool IsSuspended();
|
||||
virtual bool IsTransportSeekable() MOZ_OVERRIDE;
|
||||
|
||||
virtual size_t SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE {
|
||||
// Might be useful to track in the future:
|
||||
// - mListener (seems minor)
|
||||
// - mChannelStatistics (seems minor)
|
||||
// owned if RecordStatisticsTo is not called
|
||||
// - mDataReceivedEvent (seems minor)
|
||||
size_t size = BaseMediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mCacheStream.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
class Listener MOZ_FINAL : public nsIStreamListener,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink
|
||||
|
@ -1144,6 +1144,19 @@ MediaStreamGraphImpl::ResumeAllAudioOutputs()
|
||||
}
|
||||
}
|
||||
|
||||
struct AutoProfilerUnregisterThread
|
||||
{
|
||||
// The empty ctor is used to silence a pre-4.8.0 GCC unused variable warning.
|
||||
AutoProfilerUnregisterThread()
|
||||
{
|
||||
}
|
||||
|
||||
~AutoProfilerUnregisterThread()
|
||||
{
|
||||
profiler_unregister_thread();
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
MediaStreamGraphImpl::RunThread()
|
||||
{
|
||||
@ -1156,6 +1169,7 @@ MediaStreamGraphImpl::RunThread()
|
||||
"Shouldn't have started a graph with empty message queue!");
|
||||
|
||||
uint32_t ticksProcessed = 0;
|
||||
AutoProfilerUnregisterThread autoUnregister;
|
||||
|
||||
for (;;) {
|
||||
// Update mCurrentTime to the min of the playing audio times, or using the
|
||||
@ -1320,8 +1334,6 @@ MediaStreamGraphImpl::RunThread()
|
||||
messageQueue.SwapElements(mMessageQueue);
|
||||
}
|
||||
}
|
||||
|
||||
profiler_unregister_thread();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -69,6 +69,17 @@ public:
|
||||
MOZ_COUNT_DTOR(RtspTrackBuffer);
|
||||
mRingBuffer = nullptr;
|
||||
};
|
||||
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
// including this
|
||||
size_t size = aMallocSizeOf(this);
|
||||
|
||||
// excluding this
|
||||
size += mRingBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void Start() {
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
mIsStarted = true;
|
||||
@ -369,6 +380,23 @@ RtspMediaResource::~RtspMediaResource()
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
RtspMediaResource::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t size = BaseMediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mTrackBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
// Include the size of each track buffer.
|
||||
for (size_t i = 0; i < mTrackBuffer.Length(); i++) {
|
||||
size += mTrackBuffer[i]->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// Could add in the future:
|
||||
// - mMediaStreamController
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(RtspMediaResource::Listener,
|
||||
nsIInterfaceRequestor, nsIStreamingProtocolListener);
|
||||
|
||||
|
@ -185,6 +185,14 @@ public:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
|
||||
|
||||
virtual size_t SizeOfIncludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// Listener implements nsIStreamingProtocolListener as
|
||||
// mMediaStreamController's callback function.
|
||||
// It holds RtspMediaResource reference to notify the connection status and
|
||||
|
@ -133,6 +133,21 @@ public:
|
||||
virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
|
||||
virtual const nsCString& GetContentType() const MOZ_OVERRIDE { return mType; }
|
||||
|
||||
virtual size_t SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mType.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
private:
|
||||
const nsAutoCString mType;
|
||||
};
|
||||
|
@ -52,6 +52,16 @@ private:
|
||||
mData.AppendElements(aData, aSize);
|
||||
}
|
||||
nsTArray<uint8_t> mData;
|
||||
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
// size including this
|
||||
size_t size = aMallocSizeOf(this);
|
||||
|
||||
// size excluding this
|
||||
size += mData.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
class ResourceQueueDeallocator : public nsDequeFunctor {
|
||||
@ -175,6 +185,20 @@ private:
|
||||
}
|
||||
return evicted;
|
||||
}
|
||||
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
// Calculate the size of the internal deque.
|
||||
size_t size = nsDeque::SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
// Sum the ResourceItems.
|
||||
for (int32_t i = 0; i < nsDeque::GetSize(); ++i) {
|
||||
const ResourceItem* item =
|
||||
static_cast<const ResourceItem*>(nsDeque::ObjectAt(i));
|
||||
size += item->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
@ -226,6 +250,26 @@ public:
|
||||
|
||||
virtual const nsCString& GetContentType() const MOZ_OVERRIDE { return mType; }
|
||||
|
||||
virtual size_t SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
|
||||
// Not owned:
|
||||
// - mPrincipal
|
||||
size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mType.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
size += mInputBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// Used by SourceBuffer.
|
||||
void AppendData(const uint8_t* aData, uint32_t aLength);
|
||||
void Ended();
|
||||
@ -244,7 +288,7 @@ private:
|
||||
// Protects all of the member variables below. Read() will await a
|
||||
// Notify() (from Seek, AppendData, Ended, or Close) when insufficient
|
||||
// data is available in mData.
|
||||
ReentrantMonitor mMonitor;
|
||||
mutable ReentrantMonitor mMonitor;
|
||||
|
||||
// The buffer holding resource data is a queue of ResourceItem's.
|
||||
ResourceQueue mInputBuffer;
|
||||
|
@ -22,6 +22,14 @@ OggWriter::OggWriter() : ContainerWriter()
|
||||
}
|
||||
}
|
||||
|
||||
OggWriter::~OggWriter()
|
||||
{
|
||||
if (mInitialized) {
|
||||
ogg_stream_clear(&mOggStreamState);
|
||||
}
|
||||
// mPacket's data was always owned by us, no need to ogg_packet_clear.
|
||||
}
|
||||
|
||||
nsresult
|
||||
OggWriter::Init()
|
||||
{
|
||||
|
@ -22,6 +22,7 @@ class OggWriter : public ContainerWriter
|
||||
{
|
||||
public:
|
||||
OggWriter();
|
||||
~OggWriter();
|
||||
|
||||
nsresult WriteEncodedTrack(const EncodedFrameContainer &aData,
|
||||
uint32_t aFlags = 0) MOZ_OVERRIDE;
|
||||
|
@ -287,6 +287,7 @@ TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t
|
||||
, mUpdateHitRegion(false)
|
||||
, mContextMenuHandled(false)
|
||||
, mWaitingTouchListeners(false)
|
||||
, mIgnoreKeyPressEvent(false)
|
||||
{
|
||||
if (!sActiveDurationMsSet) {
|
||||
Preferences::AddIntVarCache(&sActiveDurationMs,
|
||||
@ -1910,8 +1911,19 @@ TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent,
|
||||
bool
|
||||
TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event)
|
||||
{
|
||||
// If content code called preventDefault() on a keydown event, then we don't
|
||||
// want to process any following keypress events.
|
||||
if (event.message == NS_KEY_PRESS && mIgnoreKeyPressEvent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
WidgetKeyboardEvent localEvent(event);
|
||||
DispatchWidgetEvent(localEvent);
|
||||
nsEventStatus status = DispatchWidgetEvent(localEvent);
|
||||
|
||||
if (event.message == NS_KEY_DOWN) {
|
||||
mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -508,6 +508,8 @@ private:
|
||||
bool mWaitingTouchListeners;
|
||||
void FireSingleTapEvent(LayoutDevicePoint aPoint);
|
||||
|
||||
bool mIgnoreKeyPressEvent;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
||||
};
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "nsRegion.h"
|
||||
#include <vector>
|
||||
#include "mozilla/WidgetUtils.h"
|
||||
|
||||
/**
|
||||
* Different elements of a web pages are rendered into separate "layers" before
|
||||
@ -201,6 +202,7 @@ public:
|
||||
: mCompositorID(0)
|
||||
, mDiagnosticTypes(DIAGNOSTIC_NONE)
|
||||
, mParent(aParent)
|
||||
, mScreenRotation(ROTATION_0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(Compositor);
|
||||
}
|
||||
@ -480,6 +482,30 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScreenRotation GetScreenRotation() const {
|
||||
return mScreenRotation;
|
||||
}
|
||||
|
||||
void SetScreenRotation(ScreenRotation aRotation) {
|
||||
mScreenRotation = aRotation;
|
||||
}
|
||||
|
||||
// On b2g the clip rect is in the coordinate space of the physical screen
|
||||
// independently of its rotation, while the coordinate space of the layers,
|
||||
// on the other hand, depends on the screen orientation.
|
||||
// This only applies to b2g as with other platforms, orientation is handled
|
||||
// at the OS level rather than in Gecko.
|
||||
gfx::Rect ClipRectInLayersCoordinates(gfx::Rect aClip) const {
|
||||
switch (mScreenRotation) {
|
||||
case ROTATION_90:
|
||||
case ROTATION_270:
|
||||
return gfx::Rect(aClip.y, aClip.x, aClip.height, aClip.width);
|
||||
case ROTATION_0:
|
||||
case ROTATION_180:
|
||||
default:
|
||||
return aClip;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
|
||||
const gfx::Rect& aVisibleRect,
|
||||
@ -505,6 +531,8 @@ protected:
|
||||
size_t mPixelsPerFrame;
|
||||
size_t mPixelsFilled;
|
||||
|
||||
ScreenRotation mScreenRotation;
|
||||
|
||||
private:
|
||||
static LayersBackend sBackend;
|
||||
|
||||
|
@ -281,57 +281,6 @@ ImageContainer::LockCurrentImage()
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
ImageContainer::DeprecatedLockCurrentAsSurface(gfx::IntSize *aSize, Image** aCurrentImage)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mRemoteData) {
|
||||
NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
|
||||
mRemoteDataMutex->Lock();
|
||||
|
||||
EnsureActiveImage();
|
||||
|
||||
if (aCurrentImage) {
|
||||
NS_IF_ADDREF(mActiveImage);
|
||||
*aCurrentImage = mActiveImage.get();
|
||||
}
|
||||
|
||||
if (!mActiveImage) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
|
||||
nsRefPtr<gfxImageSurface> newSurf =
|
||||
new gfxImageSurface(mRemoteData->mBitmap.mData,
|
||||
ThebesIntSize(mRemoteData->mSize),
|
||||
mRemoteData->mBitmap.mStride,
|
||||
mRemoteData->mFormat == RemoteImageData::BGRX32 ?
|
||||
gfxImageFormat::ARGB32 :
|
||||
gfxImageFormat::RGB24);
|
||||
|
||||
*aSize = newSurf->GetSize().ToIntSize();
|
||||
|
||||
return newSurf.forget();
|
||||
}
|
||||
|
||||
*aSize = mActiveImage->GetSize();
|
||||
return mActiveImage->DeprecatedGetAsSurface();
|
||||
}
|
||||
|
||||
if (aCurrentImage) {
|
||||
NS_IF_ADDREF(mActiveImage);
|
||||
*aCurrentImage = mActiveImage.get();
|
||||
}
|
||||
|
||||
if (!mActiveImage) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*aSize = mActiveImage->GetSize();
|
||||
return mActiveImage->DeprecatedGetAsSurface();
|
||||
}
|
||||
|
||||
TemporaryRef<gfx::SourceSurface>
|
||||
ImageContainer::LockCurrentAsSourceSurface(gfx::IntSize *aSize, Image** aCurrentImage)
|
||||
{
|
||||
|
@ -522,17 +522,6 @@ public:
|
||||
*/
|
||||
already_AddRefed<gfxASurface> DeprecatedGetCurrentAsSurface(gfx::IntSize* aSizeResult);
|
||||
|
||||
/**
|
||||
* This is similar to GetCurrentAsSurface, however this does not make a copy
|
||||
* of the image data and requires the user to call UnlockCurrentImage when
|
||||
* done with the image data. Once UnlockCurrentImage has been called the
|
||||
* surface returned by this function is no longer valid! This works for any
|
||||
* type of image. Optionally a pointer can be passed to receive the current
|
||||
* image.
|
||||
*/
|
||||
already_AddRefed<gfxASurface> DeprecatedLockCurrentAsSurface(gfx::IntSize* aSizeResult,
|
||||
Image** aCurrentImage = nullptr);
|
||||
|
||||
/**
|
||||
* Same as GetCurrentAsSurface but for Moz2D
|
||||
*/
|
||||
|
@ -1308,6 +1308,13 @@ public:
|
||||
*/
|
||||
void LogSelf(const char* aPrefix="");
|
||||
|
||||
// Print interesting information about this into aTo. Internally
|
||||
// used to implement Dump*() and Log*(). If subclasses have
|
||||
// additional interesting properties, they should override this with
|
||||
// an implementation that first calls the base implementation then
|
||||
// appends additional info to aTo.
|
||||
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
|
||||
|
||||
static bool IsLogEnabled() { return LayerManager::IsLogEnabled(); }
|
||||
|
||||
/**
|
||||
@ -1351,13 +1358,6 @@ public:
|
||||
protected:
|
||||
Layer(LayerManager* aManager, void* aImplData);
|
||||
|
||||
// Print interesting information about this into aTo. Internally
|
||||
// used to implement Dump*() and Log*(). If subclasses have
|
||||
// additional interesting properties, they should override this with
|
||||
// an implementation that first calls the base implementation then
|
||||
// appends additional info to aTo.
|
||||
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
|
||||
|
||||
/**
|
||||
* We can snap layer transforms for two reasons:
|
||||
* 1) To avoid unnecessary resampling when a transform is a translation
|
||||
|
@ -403,7 +403,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
|
||||
// then null it out so we don't keep a dangling reference and leak things.
|
||||
if (mTouchCount == 0) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
mOverscrollHandoffChain.clear();
|
||||
ClearOverscrollHandoffChain();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -517,7 +517,7 @@ APZCTreeManager::ProcessTouchEvent(WidgetTouchEvent& aEvent,
|
||||
}
|
||||
if (mTouchCount == 0) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
mOverscrollHandoffChain.clear();
|
||||
ClearOverscrollHandoffChain();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -677,18 +677,58 @@ APZCTreeManager::ClearTree()
|
||||
mRootApzc = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a displacement from the screen coordinates of a source APZC to
|
||||
* the screen coordinates of a target APZC.
|
||||
* @param aTreeManager the tree manager for the APZC tree containing |aSource|
|
||||
* and |aTarget|
|
||||
* @param aSource the source APZC
|
||||
* @param aTarget the target APZC
|
||||
* @param aStartPoint the start point of the displacement
|
||||
* @param aEndPoint the end point of the displacement
|
||||
*/
|
||||
static void
|
||||
TransformDisplacement(APZCTreeManager* aTreeManager,
|
||||
AsyncPanZoomController* aSource,
|
||||
AsyncPanZoomController* aTarget,
|
||||
ScreenPoint& aStartPoint,
|
||||
ScreenPoint& aEndPoint) {
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToGecko; // ignored
|
||||
|
||||
// Convert start and end points to untransformed screen coordinates.
|
||||
aTreeManager->GetInputTransforms(aSource, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&aStartPoint, transformToApzc.Inverse());
|
||||
ApplyTransform(&aEndPoint, transformToApzc.Inverse());
|
||||
|
||||
// Convert start and end points to aTarget's transformed screen coordinates.
|
||||
aTreeManager->GetInputTransforms(aTarget, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&aStartPoint, transformToApzc);
|
||||
ApplyTransform(&aEndPoint, transformToApzc);
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, ScreenPoint aStartPoint, ScreenPoint aEndPoint,
|
||||
uint32_t aOverscrollHandoffChainIndex)
|
||||
{
|
||||
// If we have reached the end of the overscroll handoff chain, there is
|
||||
// nothing more to scroll, so we ignore the rest of the pan gesture.
|
||||
if (aOverscrollHandoffChainIndex >= mOverscrollHandoffChain.length()) {
|
||||
// Nothing more to scroll - ignore the rest of the pan gesture.
|
||||
return;
|
||||
nsRefPtr<AsyncPanZoomController> next;
|
||||
{
|
||||
// Grab tree lock to protect mOverscrollHandoffChain from concurrent
|
||||
// access from the input and compositor threads.
|
||||
// Release it before calling TransformDisplacement() as that grabs the
|
||||
// lock itself.
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
|
||||
// If we have reached the end of the overscroll handoff chain, there is
|
||||
// nothing more to scroll, so we ignore the rest of the pan gesture.
|
||||
if (aOverscrollHandoffChainIndex >= mOverscrollHandoffChain.length()) {
|
||||
// Nothing more to scroll - ignore the rest of the pan gesture.
|
||||
return;
|
||||
}
|
||||
|
||||
next = mOverscrollHandoffChain[aOverscrollHandoffChainIndex];
|
||||
}
|
||||
|
||||
nsRefPtr<AsyncPanZoomController> next = mOverscrollHandoffChain[aOverscrollHandoffChainIndex];
|
||||
if (next == nullptr)
|
||||
return;
|
||||
|
||||
@ -698,18 +738,7 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, ScreenPoint aStar
|
||||
// scroll grabbing to grab the scroll from it), don't bother doing the
|
||||
// transformations in that case.
|
||||
if (next != aPrev) {
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToGecko; // ignored
|
||||
|
||||
// Convert start and end points to untransformed screen coordinates.
|
||||
GetInputTransforms(aPrev, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&aStartPoint, transformToApzc.Inverse());
|
||||
ApplyTransform(&aEndPoint, transformToApzc.Inverse());
|
||||
|
||||
// Convert start and end points to next's transformed screen coordinates.
|
||||
GetInputTransforms(next, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&aStartPoint, transformToApzc);
|
||||
ApplyTransform(&aEndPoint, transformToApzc);
|
||||
TransformDisplacement(this, aPrev, next, aStartPoint, aEndPoint);
|
||||
}
|
||||
|
||||
// Scroll |next|. If this causes overscroll, it will call DispatchScroll()
|
||||
@ -717,9 +746,69 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, ScreenPoint aStar
|
||||
next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffChainIndex);
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::HandOffFling(AsyncPanZoomController* aPrev, ScreenPoint aVelocity)
|
||||
{
|
||||
// Build the overscroll handoff chain. This is necessary because it is
|
||||
// otherwise built on touch-start and cleared on touch-end, and a fling
|
||||
// happens after touch-end. Note that, unlike DispatchScroll() which is
|
||||
// called on every touch-move during overscroll panning,
|
||||
// HandleFlingOverscroll() is only called once during a fling handoff,
|
||||
// so it's not worth trying to avoid building the handoff chain here.
|
||||
BuildOverscrollHandoffChain(aPrev);
|
||||
|
||||
nsRefPtr<AsyncPanZoomController> next; // will be used outside monitor block
|
||||
{
|
||||
// Grab tree lock to protect mOverscrollHandoffChain from concurrent
|
||||
// access from the input and compositor threads.
|
||||
// Release it before calling GetInputTransforms() as that grabs the
|
||||
// lock itself.
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
|
||||
// Find |aPrev| in the handoff chain.
|
||||
uint32_t i;
|
||||
for (i = 0; i < mOverscrollHandoffChain.length(); ++i) {
|
||||
if (mOverscrollHandoffChain[i] == aPrev) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the next APZC in the handoff chain, if any.
|
||||
if (i + 1 < mOverscrollHandoffChain.length()) {
|
||||
next = mOverscrollHandoffChain[i + 1];
|
||||
}
|
||||
|
||||
// Clear the handoff chain so we don't maintain references to APZCs
|
||||
// unnecessarily.
|
||||
mOverscrollHandoffChain.clear();
|
||||
}
|
||||
|
||||
// Nothing to hand off fling to.
|
||||
if (next == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The fling's velocity needs to be transformed from the screen coordinates
|
||||
// of |aPrev| to the screen coordinates of |next|. To transform a velocity
|
||||
// correctly, we need to convert it to a displacement. For now, we do this
|
||||
// by anchoring it to a start point of (0, 0).
|
||||
// TODO: For this to be correct in the presence of 3D transforms, we should
|
||||
// use the end point of the touch that started the fling as the start point
|
||||
// rather than (0, 0).
|
||||
ScreenPoint startPoint; // (0, 0)
|
||||
ScreenPoint endPoint = startPoint + aVelocity;
|
||||
TransformDisplacement(this, aPrev, next, startPoint, endPoint);
|
||||
ScreenPoint transformedVelocity = endPoint - startPoint;
|
||||
|
||||
// Tell |next| to start a fling with the transformed velocity.
|
||||
next->TakeOverFling(transformedVelocity);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
APZCTreeManager::FlushRepaintsForOverscrollHandoffChain()
|
||||
{
|
||||
MonitorAutoLock lock(mTreeLock); // to access mOverscrollHandoffChain
|
||||
if (mOverscrollHandoffChain.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
@ -799,6 +888,10 @@ APZCTreeManager::BuildOverscrollHandoffChain(const nsRefPtr<AsyncPanZoomControll
|
||||
// handoff order can be different, so we build a chain of APZCs in the
|
||||
// order in which scroll will be handed off to them.
|
||||
|
||||
// Grab tree lock to protect mOverscrollHandoffChain from concurrent
|
||||
// access between the input and compositor threads.
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
|
||||
mOverscrollHandoffChain.clear();
|
||||
|
||||
// Start with the child -> parent chain.
|
||||
@ -822,6 +915,13 @@ APZCTreeManager::BuildOverscrollHandoffChain(const nsRefPtr<AsyncPanZoomControll
|
||||
CompareByScrollPriority());
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::ClearOverscrollHandoffChain()
|
||||
{
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
mOverscrollHandoffChain.clear();
|
||||
}
|
||||
|
||||
AsyncPanZoomController*
|
||||
APZCTreeManager::FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
|
@ -41,6 +41,22 @@ class Layer;
|
||||
class AsyncPanZoomController;
|
||||
class CompositorParent;
|
||||
|
||||
/**
|
||||
* ****************** NOTE ON LOCK ORDERING IN APZ **************************
|
||||
*
|
||||
* There are two kinds of locks used by APZ: APZCTreeManager::mTreeLock
|
||||
* ("the tree lock") and AsyncPanZoomController::mMonitor ("APZC locks").
|
||||
*
|
||||
* To avoid deadlock, we impose a lock ordering between these locks, which is:
|
||||
*
|
||||
* tree lock -> APZC locks
|
||||
*
|
||||
* The interpretation of the lock ordering is that if lock A precedes lock B
|
||||
* in the ordering sequence, then you must NOT wait on A while holding B.
|
||||
*
|
||||
* **************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class manages the tree of AsyncPanZoomController instances. There is one
|
||||
* instance of this class owned by each CompositorParent, and it contains as
|
||||
@ -239,10 +255,22 @@ public:
|
||||
* - TM.DispatchScroll() calls A.AttemptScroll() (since A is at index 2 in the chain)
|
||||
* - A.AttemptScroll() scrolls A. If there is overscroll, it calls TM.DispatchScroll() with index = 3.
|
||||
* - TM.DispatchScroll() discards the rest of the scroll as there are no more elements in the chain.
|
||||
*
|
||||
* Note: this should be used for panning only. For handing off overscroll for
|
||||
* a fling, use HandOffFling().
|
||||
*/
|
||||
void DispatchScroll(AsyncPanZoomController* aAPZC, ScreenPoint aStartPoint, ScreenPoint aEndPoint,
|
||||
uint32_t aOverscrollHandoffChainIndex);
|
||||
|
||||
/**
|
||||
* This is a callback for AsyncPanZoomController to call when it wants to
|
||||
* hand off overscroll from a fling.
|
||||
* @param aApzc the APZC that is handing off the fling
|
||||
* @param aVelocity the current velocity of the fling, in |aApzc|'s screen
|
||||
* pixels per millisecond
|
||||
*/
|
||||
void HandOffFling(AsyncPanZoomController* aApzc, ScreenPoint aVelocity);
|
||||
|
||||
bool FlushRepaintsForOverscrollHandoffChain();
|
||||
|
||||
protected:
|
||||
@ -279,6 +307,7 @@ private:
|
||||
nsEventStatus ProcessEvent(WidgetInputEvent& inputEvent, ScrollableLayerGuid* aOutTargetGuid);
|
||||
void UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
|
||||
const ZoomConstraints& aConstraints);
|
||||
void ClearOverscrollHandoffChain();
|
||||
|
||||
/**
|
||||
* Recursive helper function to build the APZC tree. The tree of APZC instances has
|
||||
@ -303,7 +332,9 @@ private:
|
||||
* This lock does not need to be held while manipulating a single APZC instance in
|
||||
* isolation (that is, if its tree pointers are not being accessed or mutated). The
|
||||
* lock also needs to be held when accessing the mRootApzc instance variable, as that
|
||||
* is considered part of the APZC tree management state. */
|
||||
* is considered part of the APZC tree management state.
|
||||
* Finally, the lock needs to be held when accessing mOverscrollHandoffChain.
|
||||
* IMPORTANT: See the note about lock ordering at the top of this file. */
|
||||
mozilla::Monitor mTreeLock;
|
||||
nsRefPtr<AsyncPanZoomController> mRootApzc;
|
||||
/* This tracks the APZC that should receive all inputs for the current input event block.
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "nsTArray.h" // for nsAutoTArray
|
||||
#include "TextRenderer.h" // for TextRenderer
|
||||
#include <vector>
|
||||
|
||||
namespace mozilla {
|
||||
@ -120,6 +121,32 @@ static gfx::Point GetScrollData(Layer* aLayer) {
|
||||
return origin;
|
||||
}
|
||||
|
||||
static void DrawLayerInfo(const nsIntRect& aClipRect,
|
||||
LayerManagerComposite* aManager,
|
||||
Layer* aLayer)
|
||||
{
|
||||
|
||||
if (aLayer->GetType() == Layer::LayerType::TYPE_CONTAINER) {
|
||||
// XXX - should figure out a way to render this, but for now this
|
||||
// is hard to do, since it will often get superimposed over the first
|
||||
// child of the layer, which is bad.
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString layerInfo;
|
||||
aLayer->PrintInfo(layerInfo, "");
|
||||
|
||||
nsIntRegion visibleRegion = aLayer->GetVisibleRegion();
|
||||
|
||||
uint32_t maxWidth = std::min<uint32_t>(visibleRegion.GetBounds().width, 500);
|
||||
|
||||
nsIntPoint topLeft = visibleRegion.GetBounds().TopLeft();
|
||||
aManager->GetTextRenderer()->RenderText(layerInfo.get(), gfx::IntPoint(topLeft.x, topLeft.y),
|
||||
aLayer->GetEffectiveTransform(), 16,
|
||||
maxWidth);
|
||||
|
||||
}
|
||||
|
||||
static LayerVelocityUserData* GetVelocityData(Layer* aLayer) {
|
||||
static char sLayerVelocityUserDataKey;
|
||||
void* key = reinterpret_cast<void*>(&sLayerVelocityUserDataKey);
|
||||
@ -361,6 +388,10 @@ ContainerRender(ContainerT* aContainer,
|
||||
if (gfxPrefs::LayersScrollGraph()) {
|
||||
DrawVelGraph(clipRect, aManager, layerToRender->GetLayer());
|
||||
}
|
||||
|
||||
if (gfxPrefs::DrawLayerInfo()) {
|
||||
DrawLayerInfo(clipRect, aManager, layerToRender->GetLayer());
|
||||
}
|
||||
// invariant: our GL context should be current here, I don't think we can
|
||||
// assert it though
|
||||
}
|
||||
|
13
gfx/layers/composite/FontData.h
Normal file
13
gfx/layers/composite/FontData.h
Normal file
File diff suppressed because one or more lines are too long
@ -51,6 +51,7 @@
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
#include "TextRenderer.h" // for TextRenderer
|
||||
|
||||
class gfxASurface;
|
||||
class gfxContext;
|
||||
@ -104,6 +105,7 @@ LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
|
||||
, mIsCompositorReady(false)
|
||||
, mDebugOverlayWantsNextFrame(false)
|
||||
{
|
||||
mTextRenderer = new TextRenderer(aCompositor);
|
||||
MOZ_ASSERT(aCompositor);
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ class RefLayerComposite;
|
||||
class SurfaceDescriptor;
|
||||
class ThebesLayerComposite;
|
||||
class TiledLayerComposer;
|
||||
class TextRenderer;
|
||||
struct FPSState;
|
||||
|
||||
class LayerManagerComposite : public LayerManager
|
||||
@ -227,6 +228,8 @@ public:
|
||||
|
||||
void NotifyShadowTreeTransaction();
|
||||
|
||||
TextRenderer* GetTextRenderer() { return mTextRenderer; }
|
||||
|
||||
private:
|
||||
/** Region we're clipping our current drawing to. */
|
||||
nsIntRegion mClippingRegion;
|
||||
@ -273,6 +276,8 @@ private:
|
||||
bool mInTransaction;
|
||||
bool mIsCompositorReady;
|
||||
bool mDebugOverlayWantsNextFrame;
|
||||
|
||||
RefPtr<TextRenderer> mTextRenderer;
|
||||
};
|
||||
|
||||
/**
|
||||
|
163
gfx/layers/composite/TextRenderer.cpp
Normal file
163
gfx/layers/composite/TextRenderer.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TextRenderer.h"
|
||||
#include "FontData.h"
|
||||
#include "png.h"
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/layers/Compositor.h"
|
||||
#include "mozilla/layers/TextureHost.h"
|
||||
#include "mozilla/layers/Effects.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace gfx;
|
||||
using namespace std;
|
||||
|
||||
const Float sBackgroundOpacity = 0.6f;
|
||||
const SurfaceFormat sTextureFormat = SurfaceFormat::B8G8R8A8;
|
||||
|
||||
static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
}
|
||||
|
||||
static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass)
|
||||
{
|
||||
MOZ_ASSERT(sTextureFormat == SurfaceFormat::B8G8R8A8);
|
||||
|
||||
DataSourceSurface::MappedSurface map = static_cast<TextRenderer*>(png_get_progressive_ptr(png_ptr))->GetSurfaceMap();
|
||||
|
||||
uint32_t* dst = (uint32_t*)(map.mData + map.mStride * row_num);
|
||||
|
||||
for (uint32_t x = 0; x < sTextureWidth; x++) {
|
||||
// We blend to a transparent white background, this will make text readable
|
||||
// even if it's on a dark background. Without hurting our ability to
|
||||
// interact with the content behind the text.
|
||||
Float alphaValue = Float(0xFF - new_row[x]) / 255.0f;
|
||||
Float baseValue = sBackgroundOpacity * (1.0f - alphaValue);
|
||||
Color pixelColor(baseValue, baseValue, baseValue, baseValue + alphaValue);
|
||||
dst[x] = pixelColor.ToABGR();
|
||||
}
|
||||
}
|
||||
|
||||
TextRenderer::~TextRenderer()
|
||||
{
|
||||
if (mGlyphBitmaps) {
|
||||
mGlyphBitmaps->Unmap();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TextRenderer::RenderText(const string& aText, const IntPoint& aOrigin,
|
||||
const Matrix4x4& aTransform, uint32_t aTextSize,
|
||||
uint32_t aTargetPixelWidth)
|
||||
{
|
||||
EnsureInitialized();
|
||||
|
||||
// For now we only have a bitmap font with a 16px cell size, so we just
|
||||
// scale it up if the user wants larger text.
|
||||
Float scaleFactor = Float(aTextSize) / Float(sCellHeight);
|
||||
|
||||
aTargetPixelWidth /= scaleFactor;
|
||||
|
||||
uint32_t numLines = 1;
|
||||
uint32_t maxWidth = 0;
|
||||
uint32_t lineWidth = 0;
|
||||
// Calculate the size of the surface needed to draw all the glyphs.
|
||||
for (uint32_t i = 0; i < aText.length(); i++) {
|
||||
// Insert a line break if we go past the TargetPixelWidth.
|
||||
// XXX - this has the downside of overrunning the intended width, causing
|
||||
// things at the edge of a window to be cut off.
|
||||
if (aText[i] == '\n' || (aText[i] == ' ' && lineWidth > aTargetPixelWidth)) {
|
||||
numLines++;
|
||||
lineWidth = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
lineWidth += sGlyphWidths[uint32_t(aText[i])];
|
||||
maxWidth = std::max(lineWidth, maxWidth);
|
||||
}
|
||||
|
||||
// Create a surface to draw our glyphs to.
|
||||
RefPtr<DataSourceSurface> textSurf =
|
||||
Factory::CreateDataSourceSurface(IntSize(maxWidth, numLines * sCellHeight), sTextureFormat);
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
textSurf->Map(DataSourceSurface::MapType::READ_WRITE, &map);
|
||||
|
||||
// Initialize the surface to transparent white.
|
||||
memset(map.mData, uint8_t(sBackgroundOpacity * 255.0f),
|
||||
numLines * sCellHeight * map.mStride);
|
||||
|
||||
uint32_t currentXPos = 0;
|
||||
uint32_t currentYPos = 0;
|
||||
|
||||
// Copy our glyphs onto the surface.
|
||||
for (uint32_t i = 0; i < aText.length(); i++) {
|
||||
if (aText[i] == '\n' || (aText[i] == ' ' && currentXPos > aTargetPixelWidth)) {
|
||||
currentYPos += sCellHeight;
|
||||
currentXPos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t glyphXOffset = aText[i] % (sTextureWidth / sCellWidth) * sCellWidth * BytesPerPixel(sTextureFormat);
|
||||
uint32_t truncatedLine = aText[i] / (sTextureWidth / sCellWidth);
|
||||
uint32_t glyphYOffset = truncatedLine * sCellHeight * mMap.mStride;
|
||||
|
||||
for (int y = 0; y < 16; y++) {
|
||||
memcpy(map.mData + (y + currentYPos) * map.mStride + currentXPos * BytesPerPixel(sTextureFormat),
|
||||
mMap.mData + glyphYOffset + y * mMap.mStride + glyphXOffset,
|
||||
sGlyphWidths[uint32_t(aText[i])] * BytesPerPixel(sTextureFormat));
|
||||
}
|
||||
|
||||
currentXPos += sGlyphWidths[uint32_t(aText[i])];
|
||||
}
|
||||
|
||||
textSurf->Unmap();
|
||||
|
||||
RefPtr<DataTextureSource> src = mCompositor->CreateDataTextureSource();
|
||||
|
||||
if (!src->Update(textSurf)) {
|
||||
// Upload failed.
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<EffectRGB> effect = new EffectRGB(src, true, Filter::LINEAR);
|
||||
EffectChain chain;
|
||||
chain.mPrimaryEffect = effect;
|
||||
|
||||
Matrix4x4 transform = aTransform;
|
||||
transform.Scale(scaleFactor, scaleFactor, 1.0f);
|
||||
mCompositor->DrawQuad(Rect(aOrigin.x, aOrigin.y, maxWidth, numLines * 16),
|
||||
Rect(-10000, -10000, 20000, 20000), chain, 1.0f, transform);
|
||||
}
|
||||
|
||||
void
|
||||
TextRenderer::EnsureInitialized()
|
||||
{
|
||||
if (mGlyphBitmaps) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGlyphBitmaps = Factory::CreateDataSourceSurface(IntSize(sTextureWidth, sTextureHeight), sTextureFormat);
|
||||
|
||||
mGlyphBitmaps->Map(DataSourceSurface::MapType::READ_WRITE, &mMap);
|
||||
|
||||
png_structp png_ptr = NULL;
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
|
||||
png_set_progressive_read_fn(png_ptr, this, info_callback, row_callback, nullptr);
|
||||
png_infop info_ptr = NULL;
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
|
||||
png_process_data(png_ptr, info_ptr, (uint8_t*)sFontPNG, sizeof(sFontPNG));
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
46
gfx/layers/composite/TextRenderer.h
Normal file
46
gfx/layers/composite/TextRenderer.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_TextRenderer_H
|
||||
#define GFX_TextRenderer_H
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include <string>
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Compositor;
|
||||
|
||||
class TextRenderer : public RefCounted<TextRenderer>
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(TextRenderer)
|
||||
TextRenderer(Compositor *aCompositor)
|
||||
: mCompositor(aCompositor)
|
||||
{
|
||||
}
|
||||
|
||||
~TextRenderer();
|
||||
|
||||
void RenderText(const std::string& aText, const gfx::IntPoint& aOrigin,
|
||||
const gfx::Matrix4x4& aTransform, uint32_t aTextSize,
|
||||
uint32_t aTargetPixelWidth);
|
||||
|
||||
gfx::DataSourceSurface::MappedSurface& GetSurfaceMap() { return mMap; }
|
||||
|
||||
private:
|
||||
|
||||
void EnsureInitialized();
|
||||
|
||||
RefPtr<Compositor> mCompositor;
|
||||
RefPtr<gfx::DataSourceSurface> mGlyphBitmaps;
|
||||
gfx::DataSourceSurface::MappedSurface mMap;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -26,6 +26,7 @@
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "nsSize.h" // for nsIntSize
|
||||
#include "nsString.h" // for nsAutoCString
|
||||
#include "TextRenderer.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -322,7 +322,7 @@ TiledContentHost::RenderTile(const TileHost& aTile,
|
||||
Rect quad(screenBounds.x, screenBounds.y, screenBounds.width, screenBounds.height);
|
||||
quad = mat.TransformBounds(quad);
|
||||
|
||||
if (!quad.Intersects(aClipRect)) {
|
||||
if (!quad.Intersects(mCompositor->ClipRectInLayersCoordinates(aClipRect))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -312,6 +312,13 @@ static bool IsCloseToVertical(float aAngle, float aThreshold)
|
||||
return (fabs(aAngle - (M_PI / 2)) < aThreshold);
|
||||
}
|
||||
|
||||
template <typename Units>
|
||||
static bool IsZero(const gfx::PointTyped<Units>& aPoint)
|
||||
{
|
||||
return FuzzyEqualsMultiplicative(aPoint.x, 0.0f)
|
||||
&& FuzzyEqualsMultiplicative(aPoint.y, 0.0f);
|
||||
}
|
||||
|
||||
static inline void LogRendertraceRect(const ScrollableLayerGuid& aGuid, const char* aDesc, const char* aColor, const CSSRect& aRect)
|
||||
{
|
||||
#ifdef APZC_ENABLE_RENDERTRACE
|
||||
@ -339,10 +346,9 @@ GetFrameTime() {
|
||||
|
||||
class FlingAnimation: public AsyncPanZoomAnimation {
|
||||
public:
|
||||
FlingAnimation(AxisX& aX, AxisY& aY)
|
||||
FlingAnimation(AsyncPanZoomController& aApzc)
|
||||
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gFlingRepaintInterval))
|
||||
, mX(aX)
|
||||
, mY(aY)
|
||||
, mApzc(aApzc)
|
||||
{}
|
||||
/**
|
||||
* Advances a fling by an interpolated amount based on the passed in |aDelta|.
|
||||
@ -354,8 +360,7 @@ public:
|
||||
const TimeDuration& aDelta);
|
||||
|
||||
private:
|
||||
AxisX& mX;
|
||||
AxisY& mY;
|
||||
AsyncPanZoomController& mApzc;
|
||||
};
|
||||
|
||||
class ZoomAnimation: public AsyncPanZoomAnimation {
|
||||
@ -750,8 +755,9 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
||||
case PANNING_LOCKED_Y:
|
||||
{
|
||||
// Make a local copy of the tree manager pointer and check if it's not
|
||||
// null before calling HandleOverscroll(). This is necessary because
|
||||
// Destroy(), which nulls out mTreeManager, could be called concurrently.
|
||||
// null before calling FlushRepaintsForOverscrollHandoffChain().
|
||||
// This is necessary because Destroy(), which nulls out mTreeManager,
|
||||
// could be called concurrently.
|
||||
APZCTreeManager* treeManagerLocal = mTreeManager;
|
||||
if (treeManagerLocal) {
|
||||
if (!treeManagerLocal->FlushRepaintsForOverscrollHandoffChain()) {
|
||||
@ -764,7 +770,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
||||
mX.EndTouch();
|
||||
mY.EndTouch();
|
||||
SetState(FLING);
|
||||
StartAnimation(new FlingAnimation(mX, mY));
|
||||
StartAnimation(new FlingAnimation(*this));
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
|
||||
case PINCHING:
|
||||
@ -1152,18 +1158,18 @@ void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
||||
CSSToScreenScale zoom = mFrameMetrics.mZoom;
|
||||
|
||||
// Inversely scale the offset by the resolution (when you're zoomed further in,
|
||||
// a larger swipe should move you a shorter distance).
|
||||
// the same swipe should move you a shorter distance).
|
||||
CSSPoint cssDisplacement = displacement / zoom;
|
||||
|
||||
CSSPoint cssOverscroll;
|
||||
gfx::Point scrollOffset(mX.AdjustDisplacement(cssDisplacement.x,
|
||||
cssOverscroll.x),
|
||||
mY.AdjustDisplacement(cssDisplacement.y,
|
||||
cssOverscroll.y));
|
||||
CSSPoint allowedDisplacement(mX.AdjustDisplacement(cssDisplacement.x,
|
||||
cssOverscroll.x),
|
||||
mY.AdjustDisplacement(cssDisplacement.y,
|
||||
cssOverscroll.y));
|
||||
overscroll = cssOverscroll * zoom;
|
||||
|
||||
if (fabs(scrollOffset.x) > EPSILON || fabs(scrollOffset.y) > EPSILON) {
|
||||
ScrollBy(CSSPoint::FromUnknownPoint(scrollOffset));
|
||||
if (!IsZero(allowedDisplacement)) {
|
||||
ScrollBy(allowedDisplacement);
|
||||
ScheduleComposite();
|
||||
|
||||
TimeDuration timePaintDelta = mPaintThrottler.TimeSinceLastRequest(GetFrameTime());
|
||||
@ -1174,17 +1180,26 @@ void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
||||
}
|
||||
}
|
||||
|
||||
if (fabs(overscroll.x) > EPSILON || fabs(overscroll.y) > EPSILON) {
|
||||
if (!IsZero(overscroll)) {
|
||||
// "+ overscroll" rather than "- overscroll" because "overscroll" is what's
|
||||
// left of "displacement", and "displacement" is "start - end".
|
||||
CallDispatchScroll(aEndPoint + overscroll, aEndPoint, aOverscrollHandoffChainIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::TakeOverFling(ScreenPoint aVelocity) {
|
||||
// We may have a pre-existing velocity for whatever reason (for example,
|
||||
// a previously handed off fling). We don't want to clobber that.
|
||||
mX.SetVelocity(mX.GetVelocity() + aVelocity.x);
|
||||
mY.SetVelocity(mY.GetVelocity() + aVelocity.y);
|
||||
SetState(FLING);
|
||||
StartAnimation(new FlingAnimation(*this));
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::CallDispatchScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
|
||||
uint32_t aOverscrollHandoffChainIndex) {
|
||||
// Make a local copy of the tree manager pointer and check if it's not
|
||||
// null before calling HandleOverscroll(). This is necessary because
|
||||
// null before calling DispatchScroll(). This is necessary because
|
||||
// Destroy(), which nulls out mTreeManager, could be called concurrently.
|
||||
APZCTreeManager* treeManagerLocal = mTreeManager;
|
||||
if (treeManagerLocal) {
|
||||
@ -1240,24 +1255,76 @@ ScreenIntPoint& AsyncPanZoomController::GetFirstTouchScreenPoint(const MultiTouc
|
||||
|
||||
bool FlingAnimation::Sample(FrameMetrics& aFrameMetrics,
|
||||
const TimeDuration& aDelta) {
|
||||
bool shouldContinueFlingX = mX.FlingApplyFrictionOrCancel(aDelta),
|
||||
shouldContinueFlingY = mY.FlingApplyFrictionOrCancel(aDelta);
|
||||
|
||||
// If the fling is handed off to our APZC from a child, on the first call to
|
||||
// Sample() aDelta might be negative because it's computed as the sample time
|
||||
// from SampleContentTransformForFrame() minus our APZC's mLastSampleTime
|
||||
// which is the time the child handed off the fling from its call to
|
||||
// SampleContentTransformForFrame() with the same sample time. If we allow
|
||||
// the negative aDelta to be processed, it will yield a displacement in the
|
||||
// direction opposite to the fling, which can cause us to overscroll and
|
||||
// hand off the fling to _our_ parent, which effectively kills the fling.
|
||||
if (aDelta.ToMilliseconds() <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shouldContinueFlingX = mApzc.mX.FlingApplyFrictionOrCancel(aDelta),
|
||||
shouldContinueFlingY = mApzc.mY.FlingApplyFrictionOrCancel(aDelta);
|
||||
// If we shouldn't continue the fling, let's just stop and repaint.
|
||||
if (!shouldContinueFlingX && !shouldContinueFlingY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CSSPoint overscroll; // overscroll is ignored for flings
|
||||
ScreenPoint offset(aDelta.ToMilliseconds() * mX.GetVelocity(),
|
||||
aDelta.ToMilliseconds() * mY.GetVelocity());
|
||||
// AdjustDisplacement() zeroes out the Axis velocity if we're in overscroll.
|
||||
// Since we need to hand off the velocity to the tree manager in such a case,
|
||||
// we save it here. Would be ScreenVector instead of ScreenPoint if we had
|
||||
// vector classes.
|
||||
ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity());
|
||||
|
||||
ScreenPoint offset = velocity * aDelta.ToMilliseconds();
|
||||
|
||||
// Inversely scale the offset by the resolution (when you're zoomed further in,
|
||||
// a larger swipe should move you a shorter distance).
|
||||
// the same swipe should move you a shorter distance).
|
||||
CSSPoint cssOffset = offset / aFrameMetrics.mZoom;
|
||||
aFrameMetrics.mScrollOffset += CSSPoint::FromUnknownPoint(gfx::Point(
|
||||
mX.AdjustDisplacement(cssOffset.x, overscroll.x),
|
||||
mY.AdjustDisplacement(cssOffset.y, overscroll.y)
|
||||
));
|
||||
CSSPoint overscroll;
|
||||
aFrameMetrics.mScrollOffset += CSSPoint(
|
||||
mApzc.mX.AdjustDisplacement(cssOffset.x, overscroll.x),
|
||||
mApzc.mY.AdjustDisplacement(cssOffset.y, overscroll.y)
|
||||
);
|
||||
|
||||
// If the fling has caused us to reach the end of our scroll range, hand
|
||||
// off the fling to the next APZC in the overscroll handoff chain.
|
||||
if (!IsZero(overscroll)) {
|
||||
// We may have reached the end of the scroll range along one axis but
|
||||
// not the other. In such a case we only want to hand off the relevant
|
||||
// component of the fling.
|
||||
if (FuzzyEqualsMultiplicative(overscroll.x, 0.0f)) {
|
||||
velocity.x = 0;
|
||||
} else if (FuzzyEqualsMultiplicative(overscroll.y, 0.0f)) {
|
||||
velocity.y = 0;
|
||||
}
|
||||
|
||||
// To hand off the fling, we call APZCTreeManager::HandleFlingOverscroll()
|
||||
// which starts a new fling in the next APZC in the handoff chain with
|
||||
// the same velocity. For simplicity, the actual overscroll of the current
|
||||
// sample is discarded rather than being handed off. The compositor should
|
||||
// sample animations sufficiently frequently that this is not noticeable.
|
||||
|
||||
// Make a local copy of the tree manager pointer and check if it's not
|
||||
// null before calling HandleFlingOverscroll(). This is necessary because
|
||||
// Destroy(), which nulls out mTreeManager, could be called concurrently.
|
||||
APZCTreeManager* treeManagerLocal = mApzc.mTreeManager;
|
||||
if (treeManagerLocal) {
|
||||
// APZC is holding mMonitor, so directly calling HandleFlingOverscroll()
|
||||
// (which acquires the tree lock) would violate the lock ordering. Instead
|
||||
// we schedule HandleFlingOverscroll() to be called after mMonitor is
|
||||
// released.
|
||||
mDeferredTasks.append(NewRunnableMethod(treeManagerLocal,
|
||||
&APZCTreeManager::HandOffFling,
|
||||
&mApzc,
|
||||
velocity));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1535,6 +1602,12 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
||||
mCurrentAsyncScrollOffset = mFrameMetrics.mScrollOffset;
|
||||
}
|
||||
|
||||
// Execute tasks queued up by mAnimation's Sample() (called by
|
||||
// UpdateAnimation()) for execution after mMonitor has been released.
|
||||
if (mAnimation) {
|
||||
mAnimation->ExecuteDeferredTasks();
|
||||
}
|
||||
|
||||
// Cancel the mAsyncScrollTimeoutTask because we will fire a
|
||||
// mozbrowserasyncscroll event or renew the mAsyncScrollTimeoutTask again.
|
||||
if (mAsyncScrollTimeoutTask) {
|
||||
|
@ -40,6 +40,7 @@ class PCompositorParent;
|
||||
class ViewTransform;
|
||||
class APZCTreeManager;
|
||||
class AsyncPanZoomAnimation;
|
||||
class FlingAnimation;
|
||||
|
||||
/**
|
||||
* Controller for all panning and zooming logic. Any time a user input is
|
||||
@ -301,6 +302,12 @@ public:
|
||||
void AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
|
||||
uint32_t aOverscrollHandoffChainIndex = 0);
|
||||
|
||||
/**
|
||||
* Take over a fling with the given velocity from another APZC. Used for
|
||||
* during overscroll handoff for a fling.
|
||||
*/
|
||||
void TakeOverFling(ScreenPoint aVelocity);
|
||||
|
||||
/**
|
||||
* Returns allowed touch behavior for the given point on the scrollable layer.
|
||||
* Internally performs a kind of hit testing based on the regions constructed
|
||||
@ -650,6 +657,7 @@ protected:
|
||||
// Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the
|
||||
// monitor should be held. When setting |mState|, either the SetState()
|
||||
// function can be used, or the monitor can be held and then |mState| updated.
|
||||
// IMPORTANT: See the note about lock ordering at the top of APZCTreeManager.h.
|
||||
ReentrantMonitor mMonitor;
|
||||
|
||||
// Specifies whether we should use touch-action css property. Initialized from
|
||||
@ -747,6 +755,7 @@ private:
|
||||
RefPtr<AsyncPanZoomAnimation> mAnimation;
|
||||
|
||||
friend class Axis;
|
||||
friend class FlingAnimation;
|
||||
|
||||
/* The functions and members in this section are used to build a tree
|
||||
* structure out of APZC instances. This tree can only be walked or
|
||||
@ -864,12 +873,31 @@ public:
|
||||
virtual bool Sample(FrameMetrics& aFrameMetrics,
|
||||
const TimeDuration& aDelta) = 0;
|
||||
|
||||
/**
|
||||
* Execute the tasks in |mDeferredTasks| in order. See |mDeferredTasks|
|
||||
* for more information.
|
||||
*/
|
||||
void ExecuteDeferredTasks() {
|
||||
for (uint32_t i = 0; i < mDeferredTasks.length(); ++i) {
|
||||
mDeferredTasks[i]->Run();
|
||||
}
|
||||
mDeferredTasks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies how frequently (at most) we want to do repaints during the
|
||||
* animation sequence. TimeDuration::Forever() will cause it to only repaint
|
||||
* at the end of the animation.
|
||||
*/
|
||||
TimeDuration mRepaintInterval;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Tasks scheduled for execution after the APZC's mMonitor is released.
|
||||
* Derived classes can add tasks here in Sample(), and the APZC can call
|
||||
* ExecuteDeferredTasks() to execute them.
|
||||
*/
|
||||
Vector<Task*> mDeferredTasks;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -254,6 +254,10 @@ float Axis::GetVelocity() {
|
||||
return mAxisLocked ? 0 : mVelocity;
|
||||
}
|
||||
|
||||
void Axis::SetVelocity(float aVelocity) {
|
||||
mVelocity = aVelocity;
|
||||
}
|
||||
|
||||
float Axis::GetCompositionEnd() {
|
||||
return GetOrigin() + GetCompositionLength();
|
||||
}
|
||||
|
@ -128,6 +128,16 @@ public:
|
||||
*/
|
||||
float GetVelocity();
|
||||
|
||||
/**
|
||||
* Sets the raw velocity of this axis at this moment.
|
||||
* Intended to be called only when the axis "takes over" a velocity from
|
||||
* another APZC, in which case there are no touch points available to call
|
||||
* UpdateWithTouchAtDevicePoint. In other circumstances,
|
||||
* UpdateWithTouchAtDevicePoint should be used and the velocity calculated
|
||||
* there.
|
||||
*/
|
||||
void SetVelocity(float aVelocity);
|
||||
|
||||
/**
|
||||
* Gets the overscroll state of the axis given an additional displacement.
|
||||
* That is to say, if the given displacement is applied, this will tell you
|
||||
|
@ -211,6 +211,11 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mLayerManager && mLayerManager->GetCompositor() &&
|
||||
!targetConfig.naturalBounds().IsEmpty()) {
|
||||
mLayerManager->GetCompositor()->SetScreenRotation(targetConfig.rotation());
|
||||
}
|
||||
|
||||
// Clear fence handles used in previsou transaction.
|
||||
ClearPrevFenceHandles();
|
||||
|
||||
|
@ -251,6 +251,7 @@ UNIFIED_SOURCES += [
|
||||
'composite/ImageHost.cpp',
|
||||
'composite/ImageLayerComposite.cpp',
|
||||
'composite/LayerManagerComposite.cpp',
|
||||
'composite/TextRenderer.cpp',
|
||||
'composite/TextureHost.cpp',
|
||||
'composite/ThebesLayerComposite.cpp',
|
||||
'composite/TiledContentHost.cpp',
|
||||
|
@ -154,6 +154,7 @@ private:
|
||||
DECL_GFX_PREF(Live, "layers.draw-bigimage-borders", DrawBigImageBorders, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.draw-borders", DrawLayerBorders, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.draw-tile-borders", DrawTileBorders, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.draw-layer-info", DrawLayerInfo, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.dump", LayersDump, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.enable-tiles", LayersTilesEnabled, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.simple-tiles", LayersUseSimpleTiles, bool, false);
|
||||
|
@ -210,6 +210,14 @@ RedirectCall(void *fun, ABIFunctionType type)
|
||||
return fun;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
AssumeUnreachable()
|
||||
{
|
||||
MOZ_CRASH("Reached unreachable code in asm.js");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *
|
||||
AddressOf(AsmJSImmKind kind, ExclusiveContext *cx)
|
||||
{
|
||||
@ -274,6 +282,10 @@ AddressOf(AsmJSImmKind kind, ExclusiveContext *cx)
|
||||
return RedirectCall(FuncCast(ecmaPow), Args_Double_DoubleDouble);
|
||||
case AsmJSImm_ATan2D:
|
||||
return RedirectCall(FuncCast(ecmaAtan2), Args_Double_DoubleDouble);
|
||||
#ifdef DEBUG
|
||||
case AsmJSImm_AssumeUnreachable:
|
||||
return RedirectCall(FuncCast(AssumeUnreachable), Args_General0);
|
||||
#endif
|
||||
case AsmJSImm_Invalid:
|
||||
break;
|
||||
}
|
||||
|
@ -1279,20 +1279,24 @@ void
|
||||
MacroAssembler::assumeUnreachable(const char *output)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// AsmJS forbids use of ImmPtr.
|
||||
if (!IsCompilingAsmJS()) {
|
||||
RegisterSet regs = RegisterSet::Volatile();
|
||||
PushRegsInMask(regs);
|
||||
|
||||
Register temp = regs.takeGeneral();
|
||||
RegisterSet regs = RegisterSet::Volatile();
|
||||
PushRegsInMask(regs);
|
||||
Register temp = regs.takeGeneral();
|
||||
|
||||
// With ASLR, we can't rely on 'output' to point to the
|
||||
// same char array after serialization/deserialization.
|
||||
// It is not possible until we modify AsmJsImmPtr and
|
||||
// the underlying "patching" mechanism.
|
||||
if (IsCompilingAsmJS()) {
|
||||
setupUnalignedABICall(0, temp);
|
||||
callWithABINoProfiling(AsmJSImm_AssumeUnreachable);
|
||||
} else {
|
||||
setupUnalignedABICall(1, temp);
|
||||
movePtr(ImmPtr(output), temp);
|
||||
passABIArg(temp);
|
||||
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, AssumeUnreachable_));
|
||||
|
||||
PopRegsInMask(RegisterSet::Volatile());
|
||||
}
|
||||
PopRegsInMask(RegisterSet::Volatile());
|
||||
#endif
|
||||
|
||||
breakpoint();
|
||||
|
@ -704,6 +704,9 @@ enum AsmJSImmKind
|
||||
AsmJSImm_LogD,
|
||||
AsmJSImm_PowD,
|
||||
AsmJSImm_ATan2D,
|
||||
#ifdef DEBUG
|
||||
AsmJSImm_AssumeUnreachable,
|
||||
#endif
|
||||
AsmJSImm_Invalid
|
||||
};
|
||||
|
||||
|
@ -1228,8 +1228,10 @@ nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame,
|
||||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine,
|
||||
int32_t aNumFramesOnLine)
|
||||
nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine,
|
||||
int32_t aNumFramesOnLine,
|
||||
WritingMode aLineWM,
|
||||
nscoord& aLineWidth)
|
||||
{
|
||||
// If this line consists of a line frame, reorder the line frame's children.
|
||||
if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) {
|
||||
@ -1242,7 +1244,7 @@ nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine,
|
||||
}
|
||||
|
||||
BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine);
|
||||
RepositionInlineFrames(&bld, aFirstFrameOnLine);
|
||||
RepositionInlineFrames(&bld, aFirstFrameOnLine, aLineWM, aLineWidth);
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
@ -1282,22 +1284,20 @@ nsBidiPresUtils::GetFrameBaseLevel(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::IsLeftOrRightMost(nsIFrame* aFrame,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
bool& aIsLeftMost /* out */,
|
||||
bool& aIsRightMost /* out */)
|
||||
nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
bool& aIsFirst /* out */,
|
||||
bool& aIsLast /* out */)
|
||||
{
|
||||
const nsStyleVisibility* vis = aFrame->StyleVisibility();
|
||||
bool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection);
|
||||
|
||||
/*
|
||||
* Since we lay out frames from left to right (in both LTR and RTL), visiting a
|
||||
* frame with 'mFirstVisualFrame == nullptr', means it's the first appearance of
|
||||
* one of its continuation chain frames on the line.
|
||||
* To determine if it's the last visual frame of its continuation chain on the line
|
||||
* or not, we count the number of frames of the chain on the line, and then reduce
|
||||
* it when we lay out a frame of the chain. If this value becomes 1 it means
|
||||
* that it's the last visual frame of its continuation chain on this line.
|
||||
* Since we lay out frames in the line's direction, visiting a frame with
|
||||
* 'mFirstVisualFrame == nullptr', means it's the first appearance of one
|
||||
* of its continuation chain frames on the line.
|
||||
* To determine if it's the last visual frame of its continuation chain on
|
||||
* the line or not, we count the number of frames of the chain on the line,
|
||||
* and then reduce it when we lay out a frame of the chain. If this value
|
||||
* becomes 1 it means that it's the last visual frame of its continuation
|
||||
* chain on this line.
|
||||
*/
|
||||
|
||||
nsFrameContinuationState* frameState = aContinuationStates->GetEntry(aFrame);
|
||||
@ -1334,20 +1334,18 @@ nsBidiPresUtils::IsLeftOrRightMost(nsIFrame* aFrame,
|
||||
}
|
||||
frameState->mHasContOnNextLines = (frame != nullptr);
|
||||
|
||||
aIsLeftMost = isLTR ? !frameState->mHasContOnPrevLines
|
||||
: !frameState->mHasContOnNextLines;
|
||||
aIsFirst = !frameState->mHasContOnPrevLines;
|
||||
firstFrameState = frameState;
|
||||
} else {
|
||||
// aFrame is not the first visual frame of its continuation chain
|
||||
aIsLeftMost = false;
|
||||
aIsFirst = false;
|
||||
firstFrameState = aContinuationStates->GetEntry(frameState->mFirstVisualFrame);
|
||||
}
|
||||
|
||||
aIsRightMost = (firstFrameState->mFrameCount == 1) &&
|
||||
(isLTR ? !firstFrameState->mHasContOnNextLines
|
||||
: !firstFrameState->mHasContOnPrevLines);
|
||||
aIsLast = (firstFrameState->mFrameCount == 1 &&
|
||||
!firstFrameState->mHasContOnNextLines);
|
||||
|
||||
if ((aIsLeftMost || aIsRightMost) &&
|
||||
if ((aIsFirst || aIsLast) &&
|
||||
(aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
|
||||
// For ib splits, don't treat anything except the last part as
|
||||
// endmost or anything except the first part as startmost.
|
||||
@ -1355,19 +1353,11 @@ nsBidiPresUtils::IsLeftOrRightMost(nsIFrame* aFrame,
|
||||
nsIFrame* firstContinuation = aFrame->FirstContinuation();
|
||||
if (firstContinuation->FrameIsNonLastInIBSplit()) {
|
||||
// We are not endmost
|
||||
if (isLTR) {
|
||||
aIsRightMost = false;
|
||||
} else {
|
||||
aIsLeftMost = false;
|
||||
}
|
||||
aIsLast = false;
|
||||
}
|
||||
if (firstContinuation->FrameIsNonFirstInIBSplit()) {
|
||||
// We are not startmost
|
||||
if (isLTR) {
|
||||
aIsLeftMost = false;
|
||||
} else {
|
||||
aIsRightMost = false;
|
||||
}
|
||||
aIsFirst = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1376,29 +1366,39 @@ nsBidiPresUtils::IsLeftOrRightMost(nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame,
|
||||
bool aIsOddLevel,
|
||||
nscoord& aLeft,
|
||||
nsContinuationStates* aContinuationStates)
|
||||
nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame,
|
||||
bool aIsEvenLevel,
|
||||
nscoord& aStart,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
WritingMode aLineWM,
|
||||
nscoord& aLineWidth)
|
||||
{
|
||||
if (!aFrame)
|
||||
return;
|
||||
|
||||
bool isLeftMost, isRightMost;
|
||||
IsLeftOrRightMost(aFrame,
|
||||
aContinuationStates,
|
||||
isLeftMost /* out */,
|
||||
isRightMost /* out */);
|
||||
bool isFirst, isLast;
|
||||
IsFirstOrLast(aFrame,
|
||||
aContinuationStates,
|
||||
isFirst /* out */,
|
||||
isLast /* out */);
|
||||
|
||||
WritingMode frameWM = aFrame->GetWritingMode();
|
||||
nsInlineFrame* testFrame = do_QueryFrame(aFrame);
|
||||
|
||||
//XXX temporary until GetSkipSides is logicalized
|
||||
bool isLeftMost = false, isRightMost = false;
|
||||
if (testFrame) {
|
||||
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET);
|
||||
|
||||
isLeftMost = ((isFirst && frameWM.IsBidiLTR()) ||
|
||||
(isLast && !frameWM.IsBidiLTR()));
|
||||
if (isLeftMost)
|
||||
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LEFT_MOST);
|
||||
else
|
||||
aFrame->RemoveStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LEFT_MOST);
|
||||
|
||||
isRightMost = ((isLast && frameWM.IsBidiLTR()) ||
|
||||
(isFirst && !frameWM.IsBidiLTR()));
|
||||
if (isRightMost)
|
||||
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_RIGHT_MOST);
|
||||
else
|
||||
@ -1407,26 +1407,30 @@ nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame,
|
||||
// This method is called from nsBlockFrame::PlaceLine via the call to
|
||||
// bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
|
||||
// have been reflowed, which is required for GetUsedMargin/Border/Padding
|
||||
nsMargin margin = aFrame->GetUsedMargin();
|
||||
if (isLeftMost)
|
||||
aLeft += margin.left;
|
||||
LogicalMargin margin(frameWM, aFrame->GetUsedMargin());
|
||||
if (isFirst) {
|
||||
aStart += margin.IStart(frameWM);
|
||||
}
|
||||
|
||||
nscoord start = aLeft;
|
||||
nscoord start = aStart;
|
||||
nscoord frameWidth = aFrame->GetSize().width;
|
||||
|
||||
if (!IsBidiLeaf(aFrame))
|
||||
{
|
||||
nscoord x = 0;
|
||||
nsMargin borderPadding = aFrame->GetUsedBorderAndPadding();
|
||||
if (isLeftMost) {
|
||||
x += borderPadding.left;
|
||||
nscoord iCoord = 0;
|
||||
LogicalMargin borderPadding(frameWM, aFrame->GetUsedBorderAndPadding());
|
||||
if (isFirst) {
|
||||
iCoord += borderPadding.IStart(frameWM);
|
||||
}
|
||||
|
||||
// If aIsOddLevel is true, so we need to traverse the child list
|
||||
// in reverse order, to make it O(n) we store the list locally and
|
||||
// iterate the list reversely
|
||||
// If the resolved direction of the container is different from the
|
||||
// direction of the frame, we need to traverse the child list in reverse
|
||||
// order, to make it O(n) we store the list locally and iterate the list
|
||||
// in reverse
|
||||
bool reverseOrder = aIsEvenLevel != frameWM.IsBidiLTR();
|
||||
nsTArray<nsIFrame*> childList;
|
||||
nsIFrame *frame = aFrame->GetFirstPrincipalChild();
|
||||
if (frame && aIsOddLevel) {
|
||||
if (frame && reverseOrder) {
|
||||
childList.AppendElement((nsIFrame*)nullptr);
|
||||
while (frame) {
|
||||
childList.AppendElement(frame);
|
||||
@ -1439,27 +1443,33 @@ nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame,
|
||||
int32_t index = 0;
|
||||
while (frame) {
|
||||
RepositionFrame(frame,
|
||||
aIsOddLevel,
|
||||
x,
|
||||
aContinuationStates);
|
||||
aIsEvenLevel,
|
||||
iCoord,
|
||||
aContinuationStates,
|
||||
frameWM,
|
||||
frameWidth);
|
||||
index++;
|
||||
frame = aIsOddLevel ?
|
||||
frame = reverseOrder ?
|
||||
childList[childList.Length() - index - 1] :
|
||||
frame->GetNextSibling();
|
||||
}
|
||||
|
||||
if (isRightMost) {
|
||||
x += borderPadding.right;
|
||||
if (isLast) {
|
||||
iCoord += borderPadding.IEnd(frameWM);
|
||||
}
|
||||
aLeft += x;
|
||||
aStart += iCoord;
|
||||
} else {
|
||||
aLeft += aFrame->GetSize().width;
|
||||
aStart += frameWidth;
|
||||
}
|
||||
nsRect rect = aFrame->GetRect();
|
||||
aFrame->SetRect(nsRect(start, rect.y, aLeft - start, rect.height));
|
||||
|
||||
if (isRightMost)
|
||||
aLeft += margin.right;
|
||||
LogicalRect logicalRect(aLineWM, aFrame->GetRect(), aLineWidth);
|
||||
logicalRect.IStart(aLineWM) = start;
|
||||
logicalRect.ISize(aLineWM) = aStart - start;
|
||||
aFrame->SetRect(aLineWM, logicalRect, aLineWidth);
|
||||
|
||||
if (isLast) {
|
||||
aStart += margin.IEnd(frameWM);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1484,21 +1494,23 @@ nsBidiPresUtils::InitContinuationStates(nsIFrame* aFrame,
|
||||
|
||||
void
|
||||
nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld,
|
||||
nsIFrame* aFirstChild)
|
||||
nsIFrame* aFirstChild,
|
||||
WritingMode aLineWM,
|
||||
nscoord& aLineWidth)
|
||||
{
|
||||
const nsStyleVisibility* vis = aFirstChild->StyleVisibility();
|
||||
bool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection);
|
||||
nscoord leftSpace = 0;
|
||||
nscoord startSpace = 0;
|
||||
|
||||
// This method is called from nsBlockFrame::PlaceLine via the call to
|
||||
// bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
|
||||
// have been reflowed, which is required for GetUsedMargin/Border/Padding
|
||||
nsMargin margin = aFirstChild->GetUsedMargin();
|
||||
WritingMode frameWM = aFirstChild->GetWritingMode();
|
||||
LogicalMargin margin(frameWM, aFirstChild->GetUsedMargin());
|
||||
if (!aFirstChild->GetPrevContinuation() &&
|
||||
!aFirstChild->FrameIsNonFirstInIBSplit())
|
||||
leftSpace = isLTR ? margin.left : margin.right;
|
||||
startSpace = margin.IStart(frameWM);
|
||||
|
||||
nscoord left = aFirstChild->GetPosition().x - leftSpace;
|
||||
nscoord start = LogicalRect(aLineWM, aFirstChild->GetRect(),
|
||||
aLineWidth).IStart(aLineWM) - startSpace;
|
||||
nsIFrame* frame;
|
||||
int32_t count = aBld->mVisualFrames.Length();
|
||||
int32_t index;
|
||||
@ -1511,13 +1523,25 @@ nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld,
|
||||
}
|
||||
|
||||
// Reposition frames in visual order
|
||||
for (index = 0; index < count; index++) {
|
||||
int32_t step, limit;
|
||||
if (aLineWM.IsBidiLTR()) {
|
||||
index = 0;
|
||||
step = 1;
|
||||
limit = count;
|
||||
} else {
|
||||
index = count - 1;
|
||||
step = -1;
|
||||
limit = -1;
|
||||
}
|
||||
for (; index != limit; index += step) {
|
||||
frame = aBld->VisualFrameAt(index);
|
||||
RepositionFrame(frame,
|
||||
(aBld->mLevels[aBld->mIndexMap[index]] & 1),
|
||||
left,
|
||||
&continuationStates);
|
||||
} // for
|
||||
!(aBld->mLevels[aBld->mIndexMap[index]] & 1),
|
||||
start,
|
||||
&continuationStates,
|
||||
aLineWM,
|
||||
aLineWidth);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -27,6 +27,7 @@ class nsRenderingContext;
|
||||
class nsBlockInFlowLineIterator;
|
||||
class nsStyleContext;
|
||||
template<class T> class nsTHashtable;
|
||||
namespace mozilla { class WritingMode; }
|
||||
|
||||
/**
|
||||
* A structure representing some continuation state for each frame on the line,
|
||||
@ -159,7 +160,9 @@ public:
|
||||
* @lina 05/02/2000
|
||||
*/
|
||||
static void ReorderFrames(nsIFrame* aFirstFrameOnLine,
|
||||
int32_t aNumFramesOnLine);
|
||||
int32_t aNumFramesOnLine,
|
||||
mozilla::WritingMode aLineWM,
|
||||
nscoord& aLineWidth);
|
||||
|
||||
/**
|
||||
* Format Unicode text, taking into account bidi capabilities
|
||||
@ -377,24 +380,27 @@ private:
|
||||
nsBlockInFlowLineIterator* aLineIter,
|
||||
nsIFrame* aCurrentFrame,
|
||||
BidiParagraphData* aBpd);
|
||||
|
||||
|
||||
/*
|
||||
* Position aFrame and it's descendants to their visual places. Also if aFrame
|
||||
* is not leaf, resize it to embrace it's children.
|
||||
* Position aFrame and its descendants to their visual places. Also if aFrame
|
||||
* is not leaf, resize it to embrace its children.
|
||||
*
|
||||
* @param aFrame The frame which itself and its children are going
|
||||
* to be repositioned
|
||||
* @param aIsOddLevel TRUE means the embedding level of this frame is odd
|
||||
* @param[in,out] aLeft IN value is the starting position of aFrame(without
|
||||
* considering its left margin)
|
||||
* OUT value will be the ending position of aFrame(after
|
||||
* adding its right margin)
|
||||
* @param aFrame The frame which itself and its children are
|
||||
* going to be repositioned
|
||||
* @param aIsEvenLevel TRUE means the embedding level of this frame
|
||||
* is even (LTR)
|
||||
* @param[in,out] aStart IN value is the starting position of aFrame
|
||||
* (without considering its inline-start margin)
|
||||
* OUT value will be the ending position of aFrame
|
||||
* (after adding its inline-end margin)
|
||||
* @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState
|
||||
*/
|
||||
static void RepositionFrame(nsIFrame* aFrame,
|
||||
bool aIsOddLevel,
|
||||
nscoord& aLeft,
|
||||
nsContinuationStates* aContinuationStates);
|
||||
bool aIsEvenLevel,
|
||||
nscoord& aStart,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
mozilla::WritingMode aLineWM,
|
||||
nscoord& aLineWidth);
|
||||
|
||||
/*
|
||||
* Initialize the continuation state(nsFrameContinuationState) to
|
||||
@ -422,10 +428,10 @@ private:
|
||||
* @param[out] aIsLeftMost TRUE means aFrame is leftmost frame or continuation
|
||||
* @param[out] aIsRightMost TRUE means aFrame is rightmost frame or continuation
|
||||
*/
|
||||
static void IsLeftOrRightMost(nsIFrame* aFrame,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
bool& aIsLeftMost /* out */,
|
||||
bool& aIsRightMost /* out */);
|
||||
static void IsFirstOrLast(nsIFrame* aFrame,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
bool& aIsFirst /* out */,
|
||||
bool& aIsLast /* out */);
|
||||
|
||||
/**
|
||||
* Adjust frame positions following their visual order
|
||||
@ -435,7 +441,9 @@ private:
|
||||
* @lina 04/11/2000
|
||||
*/
|
||||
static void RepositionInlineFrames(BidiLineData* aBld,
|
||||
nsIFrame* aFirstChild);
|
||||
nsIFrame* aFirstChild,
|
||||
mozilla::WritingMode aLineWM,
|
||||
nscoord& aLineWidth);
|
||||
|
||||
/**
|
||||
* Helper method for Resolve()
|
||||
|
@ -833,6 +833,12 @@ public:
|
||||
*this : LogicalMargin(aToMode, GetPhysicalMargin(aFromMode));
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (mMargin.left == 0 && mMargin.top == 0 &&
|
||||
mMargin.right == 0 && mMargin.bottom == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LogicalRect;
|
||||
|
||||
@ -1123,6 +1129,17 @@ public:
|
||||
return aWritingMode.IsVertical() ? mRect.XMost() : mRect.YMost();
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (mRect.x == 0 && mRect.y == 0 &&
|
||||
mRect.width == 0 && mRect.height == 0);
|
||||
}
|
||||
|
||||
bool IsZeroSize() const
|
||||
{
|
||||
return (mRect.width == 0 && mRect.height == 0);
|
||||
}
|
||||
|
||||
/* XXX are these correct?
|
||||
nscoord ILeft(WritingMode aWritingMode) const
|
||||
{
|
||||
|
@ -1450,7 +1450,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||
*aBottomEdgeOfChildren = bottomEdgeOfChildren;
|
||||
|
||||
#ifdef DEBUG_blocks
|
||||
if (CRAZY_WIDTH(aMetrics.Width()) || CRAZY_HEIGHT(aMetrics.Height())) {
|
||||
if (CRAZY_SIZE(aMetrics.Width()) || CRAZY_SIZE(aMetrics.Height())) {
|
||||
ListTag(stdout);
|
||||
printf(": WARNING: desired:%d,%d\n", aMetrics.Width(), aMetrics.Height());
|
||||
}
|
||||
@ -3448,35 +3448,32 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||
this, aFloatAvailableSpace.mHasFloats);
|
||||
#endif
|
||||
|
||||
nscoord x = aFloatAvailableSpace.mRect.x;
|
||||
nscoord availWidth = aFloatAvailableSpace.mRect.width;
|
||||
nscoord availHeight;
|
||||
WritingMode wm = GetWritingMode(aLine->mFirstChild);
|
||||
nscoord lineWidth = aFloatAvailableSpace.mRect.width +
|
||||
aState.BorderPadding().LeftRight();
|
||||
LogicalRect lineRect(wm, aFloatAvailableSpace.mRect, lineWidth);
|
||||
|
||||
nscoord iStart = lineRect.IStart(wm);
|
||||
|
||||
nscoord availISize = lineRect.ISize(wm);
|
||||
nscoord availBSize;
|
||||
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
||||
availHeight = NS_UNCONSTRAINEDSIZE;
|
||||
availBSize = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
else {
|
||||
/* XXX get the height right! */
|
||||
availHeight = aFloatAvailableSpace.mRect.height;
|
||||
availBSize = lineRect.BSize(wm);
|
||||
}
|
||||
|
||||
// Make sure to enable resize optimization before we call BeginLineReflow
|
||||
// because it might get disabled there
|
||||
aLine->EnableResizeReflowOptimization();
|
||||
|
||||
// For unicode-bidi: plaintext, we need to get the direction of the line from
|
||||
// the resolved paragraph level of the first frame on the line, not the block
|
||||
// frame, because the block frame could be split by hard line breaks into
|
||||
// multiple paragraphs with different base direction
|
||||
uint8_t direction =
|
||||
(StyleTextReset()->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT) ?
|
||||
nsBidiPresUtils::GetFrameBaseLevel(aLine->mFirstChild) & 1 :
|
||||
StyleVisibility()->mDirection;
|
||||
|
||||
aLineLayout.BeginLineReflow(x, aState.mY,
|
||||
availWidth, availHeight,
|
||||
aLineLayout.BeginLineReflow(iStart, aState.mY,
|
||||
availISize, availBSize,
|
||||
aFloatAvailableSpace.mHasFloats,
|
||||
false, /*XXX isTopOfPage*/
|
||||
direction);
|
||||
wm, lineWidth);
|
||||
|
||||
aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, false);
|
||||
|
||||
@ -4052,7 +4049,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||
bool addedBullet = false;
|
||||
if (HasOutsideBullet() &&
|
||||
((aLine == mLines.front() &&
|
||||
(!aLineLayout.IsZeroHeight() || (aLine == mLines.back()))) ||
|
||||
(!aLineLayout.IsZeroBSize() || (aLine == mLines.back()))) ||
|
||||
(mLines.front() != mLines.back() &&
|
||||
0 == mLines.front()->mBounds.height &&
|
||||
aLine == mLines.begin().next()))) {
|
||||
@ -4064,7 +4061,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||
aLineLayout.AddBulletFrame(bullet, metrics);
|
||||
addedBullet = true;
|
||||
}
|
||||
aLineLayout.VerticalAlignLine();
|
||||
aLineLayout.BlockDirAlignLine();
|
||||
|
||||
// We want to compare to the available space that we would have had in
|
||||
// the line's height *before* we placed any floats in the line itself.
|
||||
@ -4092,9 +4089,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||
#ifdef DEBUG
|
||||
{
|
||||
static nscoord lastHeight = 0;
|
||||
if (CRAZY_HEIGHT(aLine->mBounds.y)) {
|
||||
if (CRAZY_SIZE(aLine->mBounds.y)) {
|
||||
lastHeight = aLine->mBounds.y;
|
||||
if (abs(aLine->mBounds.y - lastHeight) > CRAZY_H/10) {
|
||||
if (abs(aLine->mBounds.y - lastHeight) > CRAZY_COORD/10) {
|
||||
nsFrame::ListTag(stdout);
|
||||
printf(": line=%p y=%d line.bounds.height=%d\n",
|
||||
static_cast<void*>(aLine.get()),
|
||||
@ -4125,20 +4122,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||
NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign) &&
|
||||
(aLineLayout.GetLineEndsInBR() ||
|
||||
IsLastLine(aState, aLine)));
|
||||
aLineLayout.HorizontalAlignFrames(aLine->mBounds, isLastLine);
|
||||
// XXX: not only bidi: right alignment can be broken after
|
||||
// RelativePositionFrames!!!
|
||||
// XXXldb Is something here considering relatively positioned frames at
|
||||
// other than their original positions?
|
||||
#ifdef IBMBIDI
|
||||
// XXXldb Why don't we do this earlier?
|
||||
if (aState.mPresContext->BidiEnabled()) {
|
||||
if (!aState.mPresContext->IsVisualMode() ||
|
||||
StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
|
||||
nsBidiPresUtils::ReorderFrames(aLine->mFirstChild, aLine->GetChildCount());
|
||||
} // not visual mode
|
||||
} // bidi enabled
|
||||
#endif // IBMBIDI
|
||||
|
||||
aLineLayout.InlineDirAlignFrames(aLine->mBounds, isLastLine,
|
||||
aLine->GetChildCount());
|
||||
|
||||
// From here on, pfd->mBounds rectangles are incorrect because bidi
|
||||
// might have moved frames around!
|
||||
|
@ -262,7 +262,7 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) {
|
||||
if (CRAZY_WIDTH(mMetrics.Width()) || CRAZY_HEIGHT(mMetrics.Height())) {
|
||||
if (CRAZY_SIZE(mMetrics.Width()) || CRAZY_SIZE(mMetrics.Height())) {
|
||||
printf("nsBlockReflowContext: ");
|
||||
nsFrame::ListTag(stdout, mFrame);
|
||||
printf(" metrics=%d,%d!\n", mMetrics.Width(), mMetrics.Height());
|
||||
|
@ -34,11 +34,8 @@ class FramePropertyTable;
|
||||
// dependency on nsDeviceContext.h. It doesn't matter if it's a
|
||||
// little off.
|
||||
#ifdef DEBUG
|
||||
#define CRAZY_W (1000000*60)
|
||||
#define CRAZY_H CRAZY_W
|
||||
|
||||
#define CRAZY_WIDTH(_x) (((_x) < -CRAZY_W) || ((_x) > CRAZY_W))
|
||||
#define CRAZY_HEIGHT(_y) (((_y) < -CRAZY_H) || ((_y) > CRAZY_H))
|
||||
#define CRAZY_COORD (1000000*60)
|
||||
#define CRAZY_SIZE(_x) (((_x) < -CRAZY_COORD) || ((_x) > CRAZY_COORD))
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -188,21 +188,10 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowState rs(aPresContext, aReflowState, kid, availSize);
|
||||
nsLineLayout ll(aPresContext, nullptr, &aReflowState, nullptr);
|
||||
|
||||
// For unicode-bidi: plaintext, we need to get the direction of the line
|
||||
// from the resolved paragraph level of the child, not the block frame,
|
||||
// because the block frame could be split by hard line breaks into
|
||||
// multiple paragraphs with different base direction
|
||||
uint8_t direction;
|
||||
nsIFrame* containerFrame = ll.LineContainerFrame();
|
||||
if (containerFrame->StyleTextReset()->mUnicodeBidi &
|
||||
NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
|
||||
FramePropertyTable *propTable = aPresContext->PropertyTable();
|
||||
direction = NS_PTR_TO_INT32(propTable->Get(kid, BaseLevelProperty())) & 1;
|
||||
} else {
|
||||
direction = containerFrame->StyleVisibility()->mDirection;
|
||||
}
|
||||
ll.BeginLineReflow(bp.left, bp.top, availSize.width, NS_UNCONSTRAINEDSIZE,
|
||||
false, true, direction);
|
||||
false, true,
|
||||
ll.LineContainerFrame()->GetWritingMode(kid),
|
||||
aReflowState.AvailableWidth());
|
||||
rs.mLineLayout = ≪
|
||||
ll.SetInFirstLetter(true);
|
||||
ll.SetFirstLetterStyleOK(true);
|
||||
|
@ -975,6 +975,20 @@ nsIFrame::GetPaddingRect() const
|
||||
return GetPaddingRectRelativeToSelf() + GetPosition();
|
||||
}
|
||||
|
||||
WritingMode
|
||||
nsIFrame::GetWritingMode(nsIFrame* aSubFrame) const
|
||||
{
|
||||
WritingMode writingMode = GetWritingMode();
|
||||
|
||||
if (!writingMode.IsVertical() &&
|
||||
(StyleTextReset()->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT)) {
|
||||
nsBidiLevel frameLevel = nsBidiPresUtils::GetFrameBaseLevel(aSubFrame);
|
||||
writingMode.SetDirectionFromBidiLevel(frameLevel);
|
||||
}
|
||||
|
||||
return writingMode;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsIFrame::GetMarginRectRelativeToSelf() const
|
||||
{
|
||||
|
@ -672,6 +672,15 @@ public:
|
||||
return mozilla::WritingMode(StyleVisibility());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the writing mode of this frame, but if it is styled with
|
||||
* unicode-bidi: plaintext, reset the direction to the resolved paragraph
|
||||
* level of the given subframe (typically the first frame on the line),
|
||||
* not this frame's writing mode, because the container frame could be split
|
||||
* by hard line breaks into multiple paragraphs with different base direction.
|
||||
*/
|
||||
mozilla::WritingMode GetWritingMode(nsIFrame* aSubFrame) const;
|
||||
|
||||
/**
|
||||
* Bounding rect of the frame. The values are in app units, and the origin is
|
||||
* relative to the upper-left of the geometric parent. The size includes the
|
||||
|
@ -487,23 +487,21 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||
nsLineLayout* lineLayout = aReflowState.mLineLayout;
|
||||
bool inFirstLine = aReflowState.mLineLayout->GetInFirstLine();
|
||||
RestyleManager* restyleManager = aPresContext->RestyleManager();
|
||||
bool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
|
||||
nscoord leftEdge = 0;
|
||||
WritingMode wm = aReflowState.GetWritingMode();
|
||||
nscoord startEdge = 0;
|
||||
// Don't offset by our start borderpadding if we have a prev continuation or
|
||||
// if we're in a part of an {ib} split other than the first one.
|
||||
if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) {
|
||||
leftEdge = ltr ? aReflowState.ComputedPhysicalBorderPadding().left
|
||||
: aReflowState.ComputedPhysicalBorderPadding().right;
|
||||
startEdge = aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
||||
}
|
||||
nscoord availableWidth = aReflowState.AvailableWidth();
|
||||
NS_ASSERTION(availableWidth != NS_UNCONSTRAINEDSIZE,
|
||||
nscoord availableISize = aReflowState.AvailableISize();
|
||||
NS_ASSERTION(availableISize != NS_UNCONSTRAINEDSIZE,
|
||||
"should no longer use available widths");
|
||||
// Subtract off left and right border+padding from availableWidth
|
||||
availableWidth -= leftEdge;
|
||||
availableWidth -= ltr ? aReflowState.ComputedPhysicalBorderPadding().right
|
||||
: aReflowState.ComputedPhysicalBorderPadding().left;
|
||||
lineLayout->BeginSpan(this, &aReflowState, leftEdge,
|
||||
leftEdge + availableWidth, &mBaseline);
|
||||
// Subtract off inline axis border+padding from availableISize
|
||||
availableISize -= startEdge;
|
||||
availableISize -= aReflowState.ComputedLogicalBorderPadding().IEnd(wm);
|
||||
lineLayout->BeginSpan(this, &aReflowState, startEdge,
|
||||
startEdge + availableISize, &mBaseline);
|
||||
|
||||
// First reflow our principal children.
|
||||
nsIFrame* frame = mFrames.FirstChild();
|
||||
@ -646,7 +644,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||
// line-height calculations. However, continuations of an inline
|
||||
// that are empty we force to empty so that things like collapsed
|
||||
// whitespace in an inline element don't affect the line-height.
|
||||
aMetrics.Width() = lineLayout->EndSpan(this);
|
||||
aMetrics.ISize() = lineLayout->EndSpan(this);
|
||||
|
||||
// Compute final width.
|
||||
|
||||
@ -654,8 +652,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||
// continuation or if we're in a part of an {ib} split other than the first
|
||||
// one.
|
||||
if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) {
|
||||
aMetrics.Width() += ltr ? aReflowState.ComputedPhysicalBorderPadding().left
|
||||
: aReflowState.ComputedPhysicalBorderPadding().right;
|
||||
aMetrics.ISize() += aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -668,8 +665,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||
if (NS_FRAME_IS_COMPLETE(aStatus) &&
|
||||
!LastInFlow()->GetNextContinuation() &&
|
||||
!FrameIsNonLastInIBSplit()) {
|
||||
aMetrics.Width() += ltr ? aReflowState.ComputedPhysicalBorderPadding().right
|
||||
: aReflowState.ComputedPhysicalBorderPadding().left;
|
||||
aMetrics.Width() += aReflowState.ComputedLogicalBorderPadding().IEnd(wm);
|
||||
}
|
||||
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@
|
||||
#include "nsBlockReflowState.h"
|
||||
#include "plarena.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "WritingModes.h"
|
||||
|
||||
class nsFloatManager;
|
||||
struct nsStyleText;
|
||||
@ -33,10 +34,10 @@ public:
|
||||
const nsLineList::iterator* aLine);
|
||||
~nsLineLayout();
|
||||
|
||||
void Init(nsBlockReflowState* aState, nscoord aMinLineHeight,
|
||||
void Init(nsBlockReflowState* aState, nscoord aMinLineBSize,
|
||||
int32_t aLineNumber) {
|
||||
mBlockRS = aState;
|
||||
mMinLineHeight = aMinLineHeight;
|
||||
mMinLineBSize = aMinLineBSize;
|
||||
mLineNumber = aLineNumber;
|
||||
}
|
||||
|
||||
@ -44,11 +45,12 @@ public:
|
||||
return mLineNumber;
|
||||
}
|
||||
|
||||
void BeginLineReflow(nscoord aX, nscoord aY,
|
||||
nscoord aWidth, nscoord aHeight,
|
||||
void BeginLineReflow(nscoord aICoord, nscoord aBCoord,
|
||||
nscoord aISize, nscoord aBSize,
|
||||
bool aImpactedByFloats,
|
||||
bool aIsTopOfPage,
|
||||
uint8_t aDirection);
|
||||
mozilla::WritingMode aWritingMode,
|
||||
nscoord aContainerWidth);
|
||||
|
||||
void EndLineReflow();
|
||||
|
||||
@ -73,7 +75,7 @@ public:
|
||||
|
||||
void SplitLineTo(int32_t aNewCount);
|
||||
|
||||
bool IsZeroHeight();
|
||||
bool IsZeroBSize();
|
||||
|
||||
// Reflows the frame and returns the reflow status. aPushedFrame is true
|
||||
// if the frame is pushed to the next line because it doesn't fit
|
||||
@ -88,11 +90,12 @@ public:
|
||||
PushFrame(aFrame);
|
||||
}
|
||||
|
||||
void VerticalAlignLine();
|
||||
void BlockDirAlignLine();
|
||||
|
||||
bool TrimTrailingWhiteSpace();
|
||||
|
||||
void HorizontalAlignFrames(nsRect& aLineBounds, bool aIsLastLine);
|
||||
void InlineDirAlignFrames(nsRect& aLineBounds, bool aIsLastLine,
|
||||
int32_t aFrameCount);
|
||||
|
||||
/**
|
||||
* Handle all the relative positioning in the line, compute the
|
||||
@ -303,10 +306,10 @@ public:
|
||||
* the right edge for RTL blocks and from the left edge for LTR blocks.
|
||||
* In other words, the current frame's distance from the line container's
|
||||
* start content edge is:
|
||||
* <code>GetCurrentFrameXDistanceFromBlock() - lineContainer->GetUsedBorderAndPadding().left</code>
|
||||
* <code>GetCurrentFrameInlineDistanceFromBlock() - lineContainer->GetUsedBorderAndPadding().left</code>
|
||||
* Note the use of <code>.left</code> for both LTR and RTL line containers.
|
||||
*/
|
||||
nscoord GetCurrentFrameXDistanceFromBlock();
|
||||
nscoord GetCurrentFrameInlineDistanceFromBlock();
|
||||
|
||||
protected:
|
||||
// This state is constant for a given block frame doing line layout
|
||||
@ -326,14 +329,22 @@ protected:
|
||||
|
||||
// Per-frame data recorded by the line-layout reflow logic. This
|
||||
// state is the state needed to post-process the line after reflow
|
||||
// has completed (vertical alignment, horizontal alignment,
|
||||
// has completed (block-direction alignment, inline-direction alignment,
|
||||
// justification and relative positioning).
|
||||
|
||||
struct PerSpanData;
|
||||
struct PerFrameData;
|
||||
friend struct PerSpanData;
|
||||
friend struct PerFrameData;
|
||||
struct PerFrameData {
|
||||
struct PerFrameData
|
||||
{
|
||||
PerFrameData(mozilla::WritingMode aWritingMode)
|
||||
: mBounds(aWritingMode)
|
||||
, mMargin(aWritingMode)
|
||||
, mBorderPadding(aWritingMode)
|
||||
, mOffsets(aWritingMode)
|
||||
{}
|
||||
|
||||
// link to next/prev frame in same span
|
||||
PerFrameData* mNext;
|
||||
PerFrameData* mPrev;
|
||||
@ -346,20 +357,23 @@ protected:
|
||||
|
||||
// From metrics
|
||||
nscoord mAscent;
|
||||
nsRect mBounds;
|
||||
// note that mBounds is a logical rect in the *line*'s writing mode.
|
||||
// When setting frame coordinates, we have to convert to the frame's
|
||||
// writing mode
|
||||
mozilla::LogicalRect mBounds;
|
||||
nsOverflowAreas mOverflowAreas;
|
||||
|
||||
// From reflow-state
|
||||
nsMargin mMargin;
|
||||
nsMargin mBorderPadding;
|
||||
nsMargin mOffsets;
|
||||
mozilla::LogicalMargin mMargin;
|
||||
mozilla::LogicalMargin mBorderPadding;
|
||||
mozilla::LogicalMargin mOffsets;
|
||||
|
||||
// state for text justification
|
||||
int32_t mJustificationNumSpaces;
|
||||
int32_t mJustificationNumLetters;
|
||||
|
||||
// Other state we use
|
||||
uint8_t mVerticalAlign;
|
||||
uint8_t mBlockDirAlign;
|
||||
|
||||
// PerFrameData flags
|
||||
#define PFD_RELATIVEPOS 0x00000001
|
||||
@ -414,19 +428,18 @@ protected:
|
||||
|
||||
const nsHTMLReflowState* mReflowState;
|
||||
bool mNoWrap;
|
||||
uint8_t mDirection;
|
||||
bool mChangedFrameDirection;
|
||||
mozilla::WritingMode mWritingMode;
|
||||
bool mZeroEffectiveSpanBox;
|
||||
bool mContainsFloat;
|
||||
bool mHasNonemptyContent;
|
||||
|
||||
nscoord mLeftEdge;
|
||||
nscoord mX;
|
||||
nscoord mRightEdge;
|
||||
nscoord mIStart;
|
||||
nscoord mICoord;
|
||||
nscoord mIEnd;
|
||||
|
||||
nscoord mTopLeading, mBottomLeading;
|
||||
nscoord mLogicalHeight;
|
||||
nscoord mMinY, mMaxY;
|
||||
nscoord mBStartLeading, mBEndLeading;
|
||||
nscoord mLogicalBSize;
|
||||
nscoord mMinBCoord, mMaxBCoord;
|
||||
nscoord* mBaseline;
|
||||
|
||||
void AppendFrame(PerFrameData* pfd) {
|
||||
@ -448,7 +461,7 @@ protected:
|
||||
int32_t mLastOptionalBreakContentOffset;
|
||||
int32_t mForceBreakContentOffset;
|
||||
|
||||
nscoord mMinLineHeight;
|
||||
nscoord mMinLineBSize;
|
||||
|
||||
// The amount of text indent that we applied to this line, needed for
|
||||
// max-element-size calculation.
|
||||
@ -462,19 +475,21 @@ protected:
|
||||
|
||||
int32_t mTotalPlacedFrames;
|
||||
|
||||
nscoord mTopEdge;
|
||||
nscoord mMaxTopBoxHeight;
|
||||
nscoord mMaxBottomBoxHeight;
|
||||
nscoord mBStartEdge;
|
||||
nscoord mMaxStartBoxBSize;
|
||||
nscoord mMaxEndBoxBSize;
|
||||
|
||||
nscoord mInflationMinFontSize;
|
||||
|
||||
// Final computed line-height value after VerticalAlignFrames for
|
||||
// Final computed line-bSize value after BlockDirAlignFrames for
|
||||
// the block has been called.
|
||||
nscoord mFinalLineHeight;
|
||||
nscoord mFinalLineBSize;
|
||||
|
||||
// Amount of trimmable whitespace width for the trailing text frame, if any
|
||||
nscoord mTrimmableWidth;
|
||||
|
||||
nscoord mContainerWidth;
|
||||
|
||||
bool mFirstLetterStyleOK : 1;
|
||||
bool mIsTopOfPage : 1;
|
||||
bool mImpactedByFloats : 1;
|
||||
@ -499,7 +514,7 @@ protected:
|
||||
/**
|
||||
* Allocate a PerFrameData from the mArena pool. The allocation is infallible.
|
||||
*/
|
||||
PerFrameData* NewPerFrameData();
|
||||
PerFrameData* NewPerFrameData(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Allocate a PerSpanData from the mArena pool. The allocation is infallible.
|
||||
@ -518,7 +533,6 @@ protected:
|
||||
nsHTMLReflowState& aReflowState);
|
||||
|
||||
bool CanPlaceFrame(PerFrameData* pfd,
|
||||
uint8_t aFrameDirection,
|
||||
bool aNotSafeToBreak,
|
||||
bool aFrameCanContinueTextRun,
|
||||
bool aCanRollBackBeforeFrame,
|
||||
@ -529,15 +543,15 @@ protected:
|
||||
void PlaceFrame(PerFrameData* pfd,
|
||||
nsHTMLReflowMetrics& aMetrics);
|
||||
|
||||
void VerticalAlignFrames(PerSpanData* psd);
|
||||
void BlockDirAlignFrames(PerSpanData* psd);
|
||||
|
||||
void PlaceTopBottomFrames(PerSpanData* psd,
|
||||
nscoord aDistanceFromTop,
|
||||
nscoord aLineHeight);
|
||||
void PlaceStartEndFrames(PerSpanData* psd,
|
||||
nscoord aDistanceFromStart,
|
||||
nscoord aLineBSize);
|
||||
|
||||
void RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflowAreas);
|
||||
|
||||
bool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaWidth);
|
||||
bool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaISize);
|
||||
|
||||
void ComputeJustificationWeights(PerSpanData* psd, int32_t* numSpaces, int32_t* numLetters);
|
||||
|
||||
|
@ -7841,7 +7841,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
||||
|
||||
iter.SetOriginalOffset(offset);
|
||||
nscoord xOffsetForTabs = (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TAB) ?
|
||||
(aLineLayout.GetCurrentFrameXDistanceFromBlock() -
|
||||
(aLineLayout.GetCurrentFrameInlineDistanceFromBlock() -
|
||||
lineContainer->GetUsedBorderAndPadding().left)
|
||||
: -1;
|
||||
PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length,
|
||||
|
@ -13,3 +13,4 @@ sctp updated to version 8263 from SVN on Sun Sep 16 00:48:48 EDT 2012
|
||||
sctp updated to version 8279 from SVN on Thu Sep 20 18:19:24 EDT 2012
|
||||
sctp updated to version 8397 from SVN on Wed Jan 9 00:41:16 EST 2013
|
||||
sctp updated to version 8443 from SVN on Sun Mar 31 09:05:07 EDT 2013
|
||||
sctp updated to version 8815 from SVN on Tue Mar 4 08:50:51 EST 2014
|
||||
|
@ -15,7 +15,6 @@ SOURCES += [
|
||||
'netinet/sctp_callout.c',
|
||||
'netinet/sctp_cc_functions.c',
|
||||
'netinet/sctp_crc32.c',
|
||||
'netinet/sctp_hashdriver.c',
|
||||
'netinet/sctp_indata.c',
|
||||
'netinet/sctp_input.c',
|
||||
'netinet/sctp_output.c',
|
||||
@ -54,7 +53,7 @@ LOCAL_INCLUDES += [
|
||||
'/xpcom/ds',
|
||||
]
|
||||
|
||||
for var in ('SCTP_SIMPLE_ALLOCATOR', 'USE_SCTP_SHA1',
|
||||
for var in ('SCTP_SIMPLE_ALLOCATOR',
|
||||
'SCTP_PROCESS_LEVEL_LOCKS', '__Userspace__', 'INET',
|
||||
'CALLBACK_API', 'SCTP_DEBUG'):
|
||||
DEFINES[var] = 1
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 246595 2013-02-09 17:26:14Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 254248 2013-08-12 13:52:15Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_H_
|
||||
@ -439,7 +439,7 @@ struct sctp_error_unrecognized_chunk {
|
||||
/* RFC4895 */
|
||||
#define SCTP_AUTHENTICATION 0x0f
|
||||
/* EY nr_sack chunk id*/
|
||||
#define SCTP_NR_SELECTIVE_ACK 0x10
|
||||
#define SCTP_NR_SELECTIVE_ACK 0x10
|
||||
/************0x40 series ***********/
|
||||
/************0x80 series ***********/
|
||||
/* RFC5061 */
|
||||
@ -533,38 +533,38 @@ struct sctp_error_unrecognized_chunk {
|
||||
/*
|
||||
* PCB Features (in sctp_features bitmask)
|
||||
*/
|
||||
#define SCTP_PCB_FLAGS_DO_NOT_PMTUD 0x00000001
|
||||
#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x00000002 /* deprecated */
|
||||
#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x00000004
|
||||
#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x00000008
|
||||
#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x00000010
|
||||
#define SCTP_PCB_FLAGS_DO_ASCONF 0x00000020
|
||||
#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x00000040
|
||||
#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x00000080
|
||||
#define SCTP_PCB_FLAGS_DO_NOT_PMTUD 0x0000000000000001
|
||||
#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x0000000000000002 /* deprecated */
|
||||
#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x0000000000000004
|
||||
#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x0000000000000008
|
||||
#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x0000000000000010
|
||||
#define SCTP_PCB_FLAGS_DO_ASCONF 0x0000000000000020
|
||||
#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x0000000000000040
|
||||
#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x0000000000000080
|
||||
/* socket options */
|
||||
#define SCTP_PCB_FLAGS_NODELAY 0x00000100
|
||||
#define SCTP_PCB_FLAGS_AUTOCLOSE 0x00000200
|
||||
#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x00000400 /* deprecated */
|
||||
#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x00000800
|
||||
#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x00001000
|
||||
#define SCTP_PCB_FLAGS_RECVPEERERR 0x00002000
|
||||
#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT 0x00004000 /* deprecated */
|
||||
#define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT 0x00008000
|
||||
#define SCTP_PCB_FLAGS_ADAPTATIONEVNT 0x00010000
|
||||
#define SCTP_PCB_FLAGS_PDAPIEVNT 0x00020000
|
||||
#define SCTP_PCB_FLAGS_AUTHEVNT 0x00040000
|
||||
#define SCTP_PCB_FLAGS_STREAM_RESETEVNT 0x00080000
|
||||
#define SCTP_PCB_FLAGS_NO_FRAGMENT 0x00100000
|
||||
#define SCTP_PCB_FLAGS_EXPLICIT_EOR 0x00400000
|
||||
#define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x00800000
|
||||
#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x01000000
|
||||
#define SCTP_PCB_FLAGS_PORTREUSE 0x02000000
|
||||
#define SCTP_PCB_FLAGS_DRYEVNT 0x04000000
|
||||
#define SCTP_PCB_FLAGS_RECVRCVINFO 0x08000000
|
||||
#define SCTP_PCB_FLAGS_RECVNXTINFO 0x10000000
|
||||
#define SCTP_PCB_FLAGS_ASSOC_RESETEVNT 0x20000000
|
||||
#define SCTP_PCB_FLAGS_STREAM_CHANGEEVNT 0x40000000
|
||||
#define SCTP_PCB_FLAGS_RECVNSENDFAILEVNT 0x80000000
|
||||
#define SCTP_PCB_FLAGS_NODELAY 0x0000000000000100
|
||||
#define SCTP_PCB_FLAGS_AUTOCLOSE 0x0000000000000200
|
||||
#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x0000000000000400 /* deprecated */
|
||||
#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x0000000000000800
|
||||
#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x0000000000001000
|
||||
#define SCTP_PCB_FLAGS_RECVPEERERR 0x0000000000002000
|
||||
#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT 0x0000000000004000 /* deprecated */
|
||||
#define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT 0x0000000000008000
|
||||
#define SCTP_PCB_FLAGS_ADAPTATIONEVNT 0x0000000000010000
|
||||
#define SCTP_PCB_FLAGS_PDAPIEVNT 0x0000000000020000
|
||||
#define SCTP_PCB_FLAGS_AUTHEVNT 0x0000000000040000
|
||||
#define SCTP_PCB_FLAGS_STREAM_RESETEVNT 0x0000000000080000
|
||||
#define SCTP_PCB_FLAGS_NO_FRAGMENT 0x0000000000100000
|
||||
#define SCTP_PCB_FLAGS_EXPLICIT_EOR 0x0000000000400000
|
||||
#define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x0000000000800000
|
||||
#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x0000000001000000
|
||||
#define SCTP_PCB_FLAGS_PORTREUSE 0x0000000002000000
|
||||
#define SCTP_PCB_FLAGS_DRYEVNT 0x0000000004000000
|
||||
#define SCTP_PCB_FLAGS_RECVRCVINFO 0x0000000008000000
|
||||
#define SCTP_PCB_FLAGS_RECVNXTINFO 0x0000000010000000
|
||||
#define SCTP_PCB_FLAGS_ASSOC_RESETEVNT 0x0000000020000000
|
||||
#define SCTP_PCB_FLAGS_STREAM_CHANGEEVNT 0x0000000040000000
|
||||
#define SCTP_PCB_FLAGS_RECVNSENDFAILEVNT 0x0000000080000000
|
||||
|
||||
/*-
|
||||
* mobility_features parameters (by micchie).Note
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 246595 2013-02-09 17:26:14Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 257803 2013-11-07 17:08:09Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -155,7 +155,10 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
|
||||
struct mbuf *m_reply = NULL;
|
||||
struct sockaddr_storage sa_store;
|
||||
struct sctp_paramhdr *ph;
|
||||
uint16_t param_type, param_length, aparam_length;
|
||||
uint16_t param_type, aparam_length;
|
||||
#if defined(INET) || defined(INET6)
|
||||
uint16_t param_length;
|
||||
#endif
|
||||
struct sockaddr *sa;
|
||||
int zero_address = 0;
|
||||
int bad_address = 0;
|
||||
@ -171,8 +174,9 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
|
||||
aparam_length = ntohs(aph->ph.param_length);
|
||||
ph = (struct sctp_paramhdr *)(aph + 1);
|
||||
param_type = ntohs(ph->param_type);
|
||||
#if defined(INET) || defined(INET6)
|
||||
param_length = ntohs(ph->param_length);
|
||||
|
||||
#endif
|
||||
sa = (struct sockaddr *)&sa_store;
|
||||
switch (param_type) {
|
||||
#ifdef INET
|
||||
@ -305,7 +309,10 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
|
||||
struct mbuf *m_reply = NULL;
|
||||
struct sockaddr_storage sa_store;
|
||||
struct sctp_paramhdr *ph;
|
||||
uint16_t param_type, param_length, aparam_length;
|
||||
uint16_t param_type, aparam_length;
|
||||
#if defined(INET) || defined(INET6)
|
||||
uint16_t param_length;
|
||||
#endif
|
||||
struct sockaddr *sa;
|
||||
int zero_address = 0;
|
||||
int result;
|
||||
@ -321,8 +328,9 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
|
||||
aparam_length = ntohs(aph->ph.param_length);
|
||||
ph = (struct sctp_paramhdr *)(aph + 1);
|
||||
param_type = ntohs(ph->param_type);
|
||||
#if defined(INET) || defined(INET6)
|
||||
param_length = ntohs(ph->param_length);
|
||||
|
||||
#endif
|
||||
sa = (struct sockaddr *)&sa_store;
|
||||
switch (param_type) {
|
||||
#ifdef INET
|
||||
@ -437,7 +445,10 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
|
||||
struct mbuf *m_reply = NULL;
|
||||
struct sockaddr_storage sa_store;
|
||||
struct sctp_paramhdr *ph;
|
||||
uint16_t param_type, param_length, aparam_length;
|
||||
uint16_t param_type, aparam_length;
|
||||
#if defined(INET) || defined(INET6)
|
||||
uint16_t param_length;
|
||||
#endif
|
||||
struct sockaddr *sa;
|
||||
int zero_address = 0;
|
||||
#ifdef INET
|
||||
@ -452,8 +463,9 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
|
||||
aparam_length = ntohs(aph->ph.param_length);
|
||||
ph = (struct sctp_paramhdr *)(aph + 1);
|
||||
param_type = ntohs(ph->param_type);
|
||||
#if defined(INET) || defined(INET6)
|
||||
param_length = ntohs(ph->param_length);
|
||||
|
||||
#endif
|
||||
sa = (struct sockaddr *)&sa_store;
|
||||
switch (param_type) {
|
||||
#ifdef INET
|
||||
@ -873,10 +885,12 @@ sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
|
||||
static uint32_t
|
||||
sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
|
||||
{
|
||||
#if defined(INET) || defined(INET6)
|
||||
uint16_t param_type, param_length;
|
||||
|
||||
param_type = ntohs(ph->param_type);
|
||||
param_length = ntohs(ph->param_length);
|
||||
#endif
|
||||
switch (sa->sa_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
@ -887,7 +901,7 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
|
||||
|
||||
v6addr = (struct sctp_ipv6addr_param *)ph;
|
||||
if ((param_type == SCTP_IPV6_ADDRESS) &&
|
||||
param_length == sizeof(struct sctp_ipv6addr_param) &&
|
||||
(param_length == sizeof(struct sctp_ipv6addr_param)) &&
|
||||
(memcmp(&v6addr->addr, &sin6->sin6_addr,
|
||||
sizeof(struct in6_addr)) == 0)) {
|
||||
return (1);
|
||||
@ -903,7 +917,7 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
|
||||
|
||||
v4addr = (struct sctp_ipv4addr_param *)ph;
|
||||
if ((param_type == SCTP_IPV4_ADDRESS) &&
|
||||
param_length == sizeof(struct sctp_ipv4addr_param) &&
|
||||
(param_length == sizeof(struct sctp_ipv4addr_param)) &&
|
||||
(memcmp(&v4addr->addr, &sin->sin_addr,
|
||||
sizeof(struct in_addr)) == 0)) {
|
||||
return (1);
|
||||
@ -1206,7 +1220,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
|
||||
uint16_t type)
|
||||
{
|
||||
struct sctp_asconf_addr *aa, *aa_next;
|
||||
struct sockaddr *sa;
|
||||
|
||||
/* make sure the request isn't already in the queue */
|
||||
TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
|
||||
@ -1269,7 +1282,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
|
||||
sa = (struct sockaddr *)sin6;
|
||||
aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
|
||||
aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
|
||||
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
|
||||
@ -1285,7 +1297,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin= (struct sockaddr_in *)&ifa->address.sa;
|
||||
sa = (struct sockaddr *)sin;
|
||||
aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
|
||||
aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
|
||||
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
|
||||
@ -1308,13 +1319,13 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
|
||||
if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
|
||||
if (type == SCTP_ADD_IP_ADDRESS) {
|
||||
SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
|
||||
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
|
||||
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
|
||||
} else if (type == SCTP_DEL_IP_ADDRESS) {
|
||||
SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
|
||||
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
|
||||
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
|
||||
} else {
|
||||
SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
|
||||
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
|
||||
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -2609,7 +2620,8 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
|
||||
/* get the parameter length */
|
||||
p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
|
||||
/* will it fit in current chunk? */
|
||||
if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) {
|
||||
if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) ||
|
||||
(SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) {
|
||||
/* won't fit, so we're done with this chunk */
|
||||
break;
|
||||
}
|
||||
@ -2730,7 +2742,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
|
||||
/* chain it all together */
|
||||
SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
|
||||
*retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
|
||||
acp->ch.chunk_length = ntohs(*retlen);
|
||||
acp->ch.chunk_length = htons(*retlen);
|
||||
|
||||
return (m_asconf_chk);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 243882 2012-12-05 08:04:20Z glebius $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 257804 2013-11-07 18:50:11Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -335,10 +335,6 @@ sctp_generate_random_key(uint32_t keylen)
|
||||
{
|
||||
sctp_key_t *new_key;
|
||||
|
||||
/* validate keylen */
|
||||
if (keylen > SCTP_AUTH_RANDOM_SIZE_MAX)
|
||||
keylen = SCTP_AUTH_RANDOM_SIZE_MAX;
|
||||
|
||||
new_key = sctp_alloc_key(keylen);
|
||||
if (new_key == NULL) {
|
||||
/* out of memory */
|
||||
@ -376,7 +372,7 @@ sctp_compare_key(sctp_key_t *key1, sctp_key_t *key2)
|
||||
uint32_t i;
|
||||
uint32_t key1len, key2len;
|
||||
uint8_t *key_1, *key_2;
|
||||
uint8_t temp[SCTP_AUTH_RANDOM_SIZE_MAX];
|
||||
uint8_t val1, val2;
|
||||
|
||||
/* sanity/length check */
|
||||
key1len = sctp_get_keylen(key1);
|
||||
@ -388,38 +384,24 @@ sctp_compare_key(sctp_key_t *key1, sctp_key_t *key2)
|
||||
else if (key2len == 0)
|
||||
return (1);
|
||||
|
||||
if (key1len != key2len) {
|
||||
if (key1len >= key2len)
|
||||
maxlen = key1len;
|
||||
else
|
||||
maxlen = key2len;
|
||||
bzero(temp, maxlen);
|
||||
if (key1len < maxlen) {
|
||||
/* prepend zeroes to key1 */
|
||||
bcopy(key1->key, temp + (maxlen - key1len), key1len);
|
||||
key_1 = temp;
|
||||
key_2 = key2->key;
|
||||
} else {
|
||||
/* prepend zeroes to key2 */
|
||||
bcopy(key2->key, temp + (maxlen - key2len), key2len);
|
||||
key_1 = key1->key;
|
||||
key_2 = temp;
|
||||
}
|
||||
if (key1len < key2len) {
|
||||
maxlen = key2len;
|
||||
} else {
|
||||
maxlen = key1len;
|
||||
key_1 = key1->key;
|
||||
key_2 = key2->key;
|
||||
}
|
||||
|
||||
key_1 = key1->key;
|
||||
key_2 = key2->key;
|
||||
/* check for numeric equality */
|
||||
for (i = 0; i < maxlen; i++) {
|
||||
if (*key_1 > *key_2)
|
||||
return (1);
|
||||
else if (*key_1 < *key_2)
|
||||
return (-1);
|
||||
key_1++;
|
||||
key_2++;
|
||||
/* left-pad with zeros */
|
||||
val1 = (i < (maxlen - key1len)) ? 0 : *(key_1++);
|
||||
val2 = (i < (maxlen - key2len)) ? 0 : *(key_2++);
|
||||
if (val1 > val2) {
|
||||
return (1);
|
||||
} else if (val1 < val2) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* keys are equal value, so check lengths */
|
||||
if (key1len == key2len)
|
||||
return (0);
|
||||
@ -703,16 +685,12 @@ sctp_auth_add_hmacid(sctp_hmaclist_t *list, uint16_t hmac_id)
|
||||
"SCTP: HMAC id list full, ignoring add %u\n", hmac_id);
|
||||
return (-1);
|
||||
}
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
if ((hmac_id != SCTP_AUTH_HMAC_ID_SHA1) &&
|
||||
#ifdef HAVE_SHA224
|
||||
(hmac_id != SCTP_AUTH_HMAC_ID_SHA224) &&
|
||||
(hmac_id != SCTP_AUTH_HMAC_ID_SHA256)) {
|
||||
#else
|
||||
if (hmac_id != SCTP_AUTH_HMAC_ID_SHA1) {
|
||||
#endif
|
||||
#ifdef HAVE_SHA2
|
||||
(hmac_id != SCTP_AUTH_HMAC_ID_SHA256) &&
|
||||
(hmac_id != SCTP_AUTH_HMAC_ID_SHA384) &&
|
||||
(hmac_id != SCTP_AUTH_HMAC_ID_SHA512) &&
|
||||
#endif
|
||||
1) {
|
||||
return (-1);
|
||||
}
|
||||
/* Now is it already in the list */
|
||||
@ -752,11 +730,18 @@ sctp_default_supported_hmaclist(void)
|
||||
{
|
||||
sctp_hmaclist_t *new_list;
|
||||
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
new_list = sctp_alloc_hmaclist(2);
|
||||
#else
|
||||
new_list = sctp_alloc_hmaclist(1);
|
||||
#endif
|
||||
if (new_list == NULL)
|
||||
return (NULL);
|
||||
(void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1);
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
/* We prefer SHA256, so list it first */
|
||||
(void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA256);
|
||||
#endif
|
||||
(void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1);
|
||||
return (new_list);
|
||||
}
|
||||
|
||||
@ -812,19 +797,13 @@ int
|
||||
sctp_verify_hmac_param (struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs)
|
||||
{
|
||||
uint32_t i;
|
||||
uint16_t hmac_id;
|
||||
uint32_t sha1_supported = 0;
|
||||
|
||||
for (i = 0; i < num_hmacs; i++) {
|
||||
hmac_id = ntohs(hmacs->hmac_ids[i]);
|
||||
if (hmac_id == SCTP_AUTH_HMAC_ID_SHA1)
|
||||
sha1_supported = 1;
|
||||
if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
/* all HMAC id's are supported */
|
||||
if (sha1_supported == 0)
|
||||
return (-1);
|
||||
else
|
||||
return (0);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sctp_authinfo_t *
|
||||
@ -878,17 +857,9 @@ sctp_get_hmac_digest_len(uint16_t hmac_algo)
|
||||
switch (hmac_algo) {
|
||||
case SCTP_AUTH_HMAC_ID_SHA1:
|
||||
return (SCTP_AUTH_DIGEST_LEN_SHA1);
|
||||
#ifdef HAVE_SHA224
|
||||
case SCTP_AUTH_HMAC_ID_SHA224:
|
||||
return (SCTP_AUTH_DIGEST_LEN_SHA224);
|
||||
#endif
|
||||
#ifdef HAVE_SHA2
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
case SCTP_AUTH_HMAC_ID_SHA256:
|
||||
return (SCTP_AUTH_DIGEST_LEN_SHA256);
|
||||
case SCTP_AUTH_HMAC_ID_SHA384:
|
||||
return (SCTP_AUTH_DIGEST_LEN_SHA384);
|
||||
case SCTP_AUTH_HMAC_ID_SHA512:
|
||||
return (SCTP_AUTH_DIGEST_LEN_SHA512);
|
||||
#endif
|
||||
default:
|
||||
/* unknown HMAC algorithm: can't do anything */
|
||||
@ -901,16 +872,10 @@ sctp_get_hmac_block_len(uint16_t hmac_algo)
|
||||
{
|
||||
switch (hmac_algo) {
|
||||
case SCTP_AUTH_HMAC_ID_SHA1:
|
||||
#ifdef HAVE_SHA224
|
||||
case SCTP_AUTH_HMAC_ID_SHA224:
|
||||
#endif
|
||||
return (64);
|
||||
#ifdef HAVE_SHA2
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
case SCTP_AUTH_HMAC_ID_SHA256:
|
||||
return (64);
|
||||
case SCTP_AUTH_HMAC_ID_SHA384:
|
||||
case SCTP_AUTH_HMAC_ID_SHA512:
|
||||
return (128);
|
||||
#endif
|
||||
case SCTP_AUTH_HMAC_ID_RSVD:
|
||||
default:
|
||||
@ -927,21 +892,11 @@ sctp_hmac_init(uint16_t hmac_algo, sctp_hash_context_t *ctx)
|
||||
{
|
||||
switch (hmac_algo) {
|
||||
case SCTP_AUTH_HMAC_ID_SHA1:
|
||||
SHA1_Init(&ctx->sha1);
|
||||
SCTP_SHA1_INIT(&ctx->sha1);
|
||||
break;
|
||||
#ifdef HAVE_SHA224
|
||||
case SCTP_AUTH_HMAC_ID_SHA224:
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_SHA2
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
case SCTP_AUTH_HMAC_ID_SHA256:
|
||||
SHA256_Init(&ctx->sha256);
|
||||
break;
|
||||
case SCTP_AUTH_HMAC_ID_SHA384:
|
||||
SHA384_Init(&ctx->sha384);
|
||||
break;
|
||||
case SCTP_AUTH_HMAC_ID_SHA512:
|
||||
SHA512_Init(&ctx->sha512);
|
||||
SCTP_SHA256_INIT(&ctx->sha256);
|
||||
break;
|
||||
#endif
|
||||
case SCTP_AUTH_HMAC_ID_RSVD:
|
||||
@ -957,21 +912,11 @@ sctp_hmac_update(uint16_t hmac_algo, sctp_hash_context_t *ctx,
|
||||
{
|
||||
switch (hmac_algo) {
|
||||
case SCTP_AUTH_HMAC_ID_SHA1:
|
||||
SHA1_Update(&ctx->sha1, text, textlen);
|
||||
SCTP_SHA1_UPDATE(&ctx->sha1, text, textlen);
|
||||
break;
|
||||
#ifdef HAVE_SHA224
|
||||
case SCTP_AUTH_HMAC_ID_SHA224:
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_SHA2
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
case SCTP_AUTH_HMAC_ID_SHA256:
|
||||
SHA256_Update(&ctx->sha256, text, textlen);
|
||||
break;
|
||||
case SCTP_AUTH_HMAC_ID_SHA384:
|
||||
SHA384_Update(&ctx->sha384, text, textlen);
|
||||
break;
|
||||
case SCTP_AUTH_HMAC_ID_SHA512:
|
||||
SHA512_Update(&ctx->sha512, text, textlen);
|
||||
SCTP_SHA256_UPDATE(&ctx->sha256, text, textlen);
|
||||
break;
|
||||
#endif
|
||||
case SCTP_AUTH_HMAC_ID_RSVD:
|
||||
@ -987,22 +932,11 @@ sctp_hmac_final(uint16_t hmac_algo, sctp_hash_context_t *ctx,
|
||||
{
|
||||
switch (hmac_algo) {
|
||||
case SCTP_AUTH_HMAC_ID_SHA1:
|
||||
SHA1_Final(digest, &ctx->sha1);
|
||||
SCTP_SHA1_FINAL(digest, &ctx->sha1);
|
||||
break;
|
||||
#ifdef HAVE_SHA224
|
||||
case SCTP_AUTH_HMAC_ID_SHA224:
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_SHA2
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
case SCTP_AUTH_HMAC_ID_SHA256:
|
||||
SHA256_Final(digest, &ctx->sha256);
|
||||
break;
|
||||
case SCTP_AUTH_HMAC_ID_SHA384:
|
||||
/* SHA384 is truncated SHA512 */
|
||||
SHA384_Final(digest, &ctx->sha384);
|
||||
break;
|
||||
case SCTP_AUTH_HMAC_ID_SHA512:
|
||||
SHA512_Final(digest, &ctx->sha512);
|
||||
SCTP_SHA256_FINAL(digest, &ctx->sha256);
|
||||
break;
|
||||
#endif
|
||||
case SCTP_AUTH_HMAC_ID_RSVD:
|
||||
|
@ -32,33 +32,28 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 235828 2012-05-23 11:26:28Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 257804 2013-11-07 18:50:11Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_AUTH_H_
|
||||
#define _NETINET_SCTP_AUTH_H_
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
|
||||
/* digest lengths */
|
||||
#define SCTP_AUTH_DIGEST_LEN_SHA1 20
|
||||
#define SCTP_AUTH_DIGEST_LEN_SHA224 28
|
||||
#define SCTP_AUTH_DIGEST_LEN_SHA256 32
|
||||
#define SCTP_AUTH_DIGEST_LEN_SHA384 48
|
||||
#define SCTP_AUTH_DIGEST_LEN_SHA512 64
|
||||
#define SCTP_AUTH_DIGEST_LEN_MAX 64
|
||||
#define SCTP_AUTH_DIGEST_LEN_MAX SCTP_AUTH_DIGEST_LEN_SHA256
|
||||
|
||||
/* random sizes */
|
||||
#define SCTP_AUTH_RANDOM_SIZE_DEFAULT 32
|
||||
#define SCTP_AUTH_RANDOM_SIZE_REQUIRED 32
|
||||
#define SCTP_AUTH_RANDOM_SIZE_MAX 256
|
||||
|
||||
/* union of all supported HMAC algorithm contexts */
|
||||
typedef union sctp_hash_context {
|
||||
SHA1_CTX sha1;
|
||||
#ifdef HAVE_SHA2
|
||||
SHA256_CTX sha256;
|
||||
SHA384_CTX sha384;
|
||||
SHA512_CTX sha512;
|
||||
SCTP_SHA1_CTX sha1;
|
||||
#if defined(SCTP_SUPPORT_HMAC_SHA256)
|
||||
SCTP_SHA256_CTX sha256;
|
||||
#endif
|
||||
} sctp_hash_context_t;
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 239035 2012-08-04 08:03:30Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 258765 2013-11-30 12:51:19Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -48,11 +48,11 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 239035 2012-08-04 08:03:30Z
|
||||
#include <netinet/sctp_asconf.h>
|
||||
#include <netinet/sctp_sysctl.h>
|
||||
#include <netinet/sctp_indata.h>
|
||||
#if !defined(__Userspace_os_Windows)
|
||||
#if defined(ANDROID)
|
||||
#include <unistd.h>
|
||||
#include <ifaddrs-android-ext.h>
|
||||
#else
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/unistd.h>
|
||||
#endif
|
||||
#endif
|
||||
@ -165,20 +165,13 @@ sctp_iterator_thread(void *v SCTP_UNUSED)
|
||||
SCTP_IPI_ITERATOR_WQ_UNLOCK();
|
||||
#if defined(__Userspace__)
|
||||
sctp_wakeup_iterator();
|
||||
#if !defined(__Userspace_os_Windows)
|
||||
pthread_exit(NULL);
|
||||
#else
|
||||
ExitThread(0);
|
||||
#endif
|
||||
return (NULL);
|
||||
#else
|
||||
wakeup(&sctp_it_ctl.iterator_flags);
|
||||
thread_terminate(current_thread());
|
||||
#endif
|
||||
#ifdef INVARIANTS
|
||||
panic("Hmm. thread_terminate() continues...");
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
return (NULL);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@ -186,46 +179,35 @@ sctp_iterator_thread(void *v SCTP_UNUSED)
|
||||
void
|
||||
sctp_startup_iterator(void)
|
||||
{
|
||||
static int called = 0;
|
||||
#if defined(__FreeBSD__) || (defined(__Userspace__) && !defined(__Userspace_os_Windows))
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
if (called) {
|
||||
if (sctp_it_ctl.thread_proc) {
|
||||
/* You only get one */
|
||||
return;
|
||||
}
|
||||
/* init the iterator head */
|
||||
called = 1;
|
||||
sctp_it_ctl.iterator_running = 0;
|
||||
sctp_it_ctl.iterator_flags = 0;
|
||||
sctp_it_ctl.cur_it = NULL;
|
||||
/* Initialize global locks here, thus only once. */
|
||||
SCTP_ITERATOR_LOCK_INIT();
|
||||
SCTP_IPI_ITERATOR_WQ_INIT();
|
||||
TAILQ_INIT(&sctp_it_ctl.iteratorhead);
|
||||
#if defined(__FreeBSD__)
|
||||
#if __FreeBSD_version <= 701000
|
||||
ret = kthread_create(sctp_iterator_thread,
|
||||
kthread_create(sctp_iterator_thread,
|
||||
#else
|
||||
ret = kproc_create(sctp_iterator_thread,
|
||||
kproc_create(sctp_iterator_thread,
|
||||
#endif
|
||||
(void *)NULL,
|
||||
&sctp_it_ctl.thread_proc,
|
||||
RFPROC,
|
||||
SCTP_KTHREAD_PAGES,
|
||||
SCTP_KTRHEAD_NAME);
|
||||
(void *)NULL,
|
||||
&sctp_it_ctl.thread_proc,
|
||||
RFPROC,
|
||||
SCTP_KTHREAD_PAGES,
|
||||
SCTP_KTRHEAD_NAME);
|
||||
#elif defined(__APPLE__)
|
||||
(void)kernel_thread_start((thread_continue_t)sctp_iterator_thread, NULL, &sctp_it_ctl.thread_proc);
|
||||
kernel_thread_start((thread_continue_t)sctp_iterator_thread, NULL, &sctp_it_ctl.thread_proc);
|
||||
#elif defined(__Userspace__)
|
||||
#if defined(__Userspace_os_Windows)
|
||||
if ((sctp_it_ctl.thread_proc = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&sctp_iterator_thread, NULL, 0, NULL)) == NULL) {
|
||||
SCTP_PRINTF("ERROR; Creating sctp_iterator_thread failed\n");
|
||||
}
|
||||
#else
|
||||
if ((ret = pthread_create(&sctp_it_ctl.thread_proc, NULL, &sctp_iterator_thread, NULL))) {
|
||||
SCTP_PRINTF("ERROR; return code from sctp_iterator_thread pthread_create() is %d\n", ret);
|
||||
}
|
||||
if (pthread_create(&sctp_it_ctl.thread_proc, NULL, &sctp_iterator_thread, NULL)) {
|
||||
#endif
|
||||
SCTP_PRINTF("ERROR: Creating sctp_iterator_thread failed.\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -341,11 +323,13 @@ sctp_is_vmware_interface(struct ifnet *ifn)
|
||||
static void
|
||||
sctp_init_ifns_for_vrf(int vrfid)
|
||||
{
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct ifaddrs *ifa;
|
||||
struct sctp_ifa *sctp_ifa;
|
||||
DWORD Err, AdapterAddrsSize;
|
||||
PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapterAddrs6, pAdapt;
|
||||
PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt;
|
||||
PIP_ADAPTER_UNICAST_ADDRESS pUnicast;
|
||||
#endif
|
||||
|
||||
#ifdef INET
|
||||
AdapterAddrsSize = 0;
|
||||
@ -372,6 +356,9 @@ sctp_init_ifns_for_vrf(int vrfid)
|
||||
for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
|
||||
if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
|
||||
for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
|
||||
if (IN4_ISLINKLOCAL_ADDRESS(&(((struct sockaddr_in *)(pUnicast->Address.lpSockaddr))->sin_addr))) {
|
||||
continue;
|
||||
}
|
||||
ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
|
||||
ifa->ifa_name = strdup(pAdapt->AdapterName);
|
||||
ifa->ifa_flags = pAdapt->Flags;
|
||||
@ -407,17 +394,17 @@ sctp_init_ifns_for_vrf(int vrfid)
|
||||
}
|
||||
}
|
||||
/* Allocate memory from sizing information */
|
||||
if ((pAdapterAddrs6 = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
|
||||
if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
|
||||
SCTP_PRINTF("Memory allocation error!\n");
|
||||
return;
|
||||
}
|
||||
/* Get actual adapter information */
|
||||
if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs6, &AdapterAddrsSize)) != ERROR_SUCCESS) {
|
||||
if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) {
|
||||
SCTP_PRINTF("GetAdaptersV6Addresses() failed with error code %d\n", Err);
|
||||
return;
|
||||
}
|
||||
/* Enumerate through each returned adapter and save its information */
|
||||
for (pAdapt = pAdapterAddrs6; pAdapt; pAdapt = pAdapt->Next) {
|
||||
for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
|
||||
if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
|
||||
for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
|
||||
ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
|
||||
@ -440,18 +427,15 @@ sctp_init_ifns_for_vrf(int vrfid)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pAdapterAddrs6)
|
||||
FREE(pAdapterAddrs6);
|
||||
if (pAdapterAddrs)
|
||||
FREE(pAdapterAddrs);
|
||||
#endif
|
||||
}
|
||||
#elif defined(__Userspace__)
|
||||
static void
|
||||
sctp_init_ifns_for_vrf(int vrfid)
|
||||
{
|
||||
/* __Userspace__ TODO struct ifaddr is defined in net/if_var.h
|
||||
* This struct contains struct ifnet, which is also defined in
|
||||
* net/if_var.h. Currently a zero byte if_var.h file is present for Linux boxes
|
||||
*/
|
||||
#if defined(INET) || defined(INET6)
|
||||
int rc;
|
||||
struct ifaddrs *ifa = NULL;
|
||||
struct sctp_ifa *sctp_ifa;
|
||||
@ -461,24 +445,39 @@ sctp_init_ifns_for_vrf(int vrfid)
|
||||
if (rc != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
#if !defined(INET)
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6) {
|
||||
/* non inet6 skip */
|
||||
continue;
|
||||
}
|
||||
#elif !defined(INET6)
|
||||
if (ifa->ifa_addr->sa_family != AF_INET) {
|
||||
/* non inet skip */
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
|
||||
/* non inet/inet6 skip */
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
if ((ifa->ifa_addr->sa_family == AF_INET6) &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
|
||||
/* skip unspecifed addresses */
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#if defined(INET)
|
||||
if (ifa->ifa_addr->sa_family == AF_INET &&
|
||||
((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
ifa_flags = 0;
|
||||
sctp_ifa = sctp_add_addr_to_vrf(vrfid,
|
||||
ifa,
|
||||
@ -493,6 +492,7 @@ sctp_init_ifns_for_vrf(int vrfid)
|
||||
sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -830,12 +830,12 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
|
||||
return (NULL);
|
||||
}
|
||||
if (allonebuf == 0)
|
||||
mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count);
|
||||
mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count);
|
||||
else
|
||||
mbuf_threshold = 1;
|
||||
|
||||
|
||||
if (space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) {
|
||||
if ((int)space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) {
|
||||
MCLGET(m, how);
|
||||
if (m == NULL) {
|
||||
return (NULL);
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 243157 2012-11-16 19:39:10Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 256556 2013-10-15 20:21:27Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_CONSTANTS_H_
|
||||
@ -557,9 +557,6 @@ extern void getwintimeofday(struct timeval *tv);
|
||||
/* How long a cookie lives in milli-seconds */
|
||||
#define SCTP_DEFAULT_COOKIE_LIFE 60000
|
||||
|
||||
/* resource limit of streams */
|
||||
#define MAX_SCTP_STREAMS 2048
|
||||
|
||||
/* Maximum the mapping array will grow to (TSN mapping array) */
|
||||
#define SCTP_MAPPING_ARRAY 512
|
||||
|
||||
@ -702,6 +699,7 @@ extern void getwintimeofday(struct timeval *tv);
|
||||
|
||||
/* How many streams I request initally by default */
|
||||
#define SCTP_OSTREAM_INITIAL 10
|
||||
#define SCTP_ISTREAM_INITIAL 2048
|
||||
|
||||
/*
|
||||
* How many smallest_mtu's need to increase before a window update sack is
|
||||
@ -776,7 +774,6 @@ extern void getwintimeofday(struct timeval *tv);
|
||||
/* small chunk store for looking at chunk_list in auth */
|
||||
#define SCTP_SMALL_CHUNK_STORE 260
|
||||
|
||||
#define SCTP_DEFAULT_MINSEGMENT 512 /* MTU size ... if no mtu disc */
|
||||
#define SCTP_HOW_MANY_SECRETS 2 /* how many secrets I keep */
|
||||
|
||||
#define SCTP_NUMBER_OF_SECRETS 8 /* or 8 * 4 = 32 octets */
|
||||
@ -1050,6 +1047,10 @@ extern void getwintimeofday(struct timeval *tv);
|
||||
(((uint8_t *)&(a)->s_addr)[2] == 0) && \
|
||||
(((uint8_t *)&(a)->s_addr)[3] == 1))
|
||||
|
||||
#define IN4_ISLINKLOCAL_ADDRESS(a) \
|
||||
((((uint8_t *)&(a)->s_addr)[0] == 169) && \
|
||||
(((uint8_t *)&(a)->s_addr)[1] == 254))
|
||||
|
||||
#if defined(__Userspace__)
|
||||
#if defined(__Userspace_os_Windows)
|
||||
#define SCTP_GETTIME_TIMEVAL(x) getwintimeofday(x)
|
||||
|
@ -40,6 +40,8 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_crc32.c 235828 2012-05-23 11:26:28Z tu
|
||||
#include <netinet/sctp_crc32.h>
|
||||
#include <netinet/sctp_pcb.h>
|
||||
|
||||
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
|
||||
#else
|
||||
/**
|
||||
@ -708,8 +710,6 @@ calculate_crc32c(uint32_t crc32c,
|
||||
}
|
||||
#endif /* FreeBSD < 80000 || other OS */
|
||||
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
|
||||
static uint32_t
|
||||
sctp_finalize_crc32c(uint32_t crc32c)
|
||||
{
|
||||
@ -785,6 +785,7 @@ sctp_calculate_cksum(struct mbuf *m, uint32_t offset)
|
||||
#endif /* !defined(SCTP_WITH_NO_CSUM) */
|
||||
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
void
|
||||
sctp_delayed_cksum(struct mbuf *m, uint32_t offset)
|
||||
{
|
||||
@ -813,4 +814,5 @@ sctp_delayed_cksum(struct mbuf *m, uint32_t offset)
|
||||
*(uint32_t *) (m->m_data + offset) = checksum;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -42,7 +42,9 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_crc32.h 235828 2012-05-23 11:26:28Z tu
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t);
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
void sctp_delayed_cksum(struct mbuf *, uint32_t offset);
|
||||
#endif
|
||||
#endif /* _KERNEL */
|
||||
#if defined(__Userspace__)
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
|
@ -1,89 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
|
||||
* Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* a) Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* b) Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* c) Neither the name of Cisco Systems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_dtrace_declare.h 235828 2012-05-23 11:26:28Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_DTRACE_DECLARE_H_
|
||||
#define _NETINET_SCTP_DTRACE_DECLARE_H_
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
|
||||
#include "opt_kdtrace.h"
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sdt.h>
|
||||
|
||||
/* Declare the SCTP provider */
|
||||
SDT_PROVIDER_DECLARE(sctp);
|
||||
|
||||
/* The probes we have so far: */
|
||||
|
||||
/* One to track a net's cwnd */
|
||||
/* initial */
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, init);
|
||||
/* update at a ack -- increase */
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, ack);
|
||||
/* update at a fast retransmit -- decrease */
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, fr);
|
||||
/* update at a time-out -- decrease */
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, to);
|
||||
/* update at a burst-limit -- decrease */
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, bl);
|
||||
/* update at a ECN -- decrease */
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, ecn);
|
||||
/* update at a Packet-Drop -- decrease */
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, pd);
|
||||
/* Rttvar probe declaration */
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, rttvar);
|
||||
SDT_PROBE_DECLARE(sctp, cwnd, net, rttstep);
|
||||
|
||||
/* One to track an associations rwnd */
|
||||
SDT_PROBE_DECLARE(sctp, rwnd, assoc, val);
|
||||
|
||||
/* One to track a net's flight size */
|
||||
SDT_PROBE_DECLARE(sctp, flightsize, net, val);
|
||||
|
||||
/* One to track an associations flight size */
|
||||
SDT_PROBE_DECLARE(sctp, flightsize, assoc, val);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#else
|
||||
/* All other platforms not defining dtrace probes */
|
||||
#ifndef SDT_PROBE
|
||||
#define SDT_PROBE(a, b, c, d, e, f, g, h, i)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
@ -1,243 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
|
||||
* Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* a) Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* b) Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* c) Neither the name of Cisco Systems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_dtrace_define.h 235828 2012-05-23 11:26:28Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_DTRACE_DEFINE_H_
|
||||
#define _NETINET_SCTP_DTRACE_DEFINE_H_
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
|
||||
#include "opt_kdtrace.h"
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sdt.h>
|
||||
|
||||
SDT_PROVIDER_DEFINE(sctp);
|
||||
|
||||
/********************************************************/
|
||||
/* Cwnd probe - tracks changes in the congestion window on a netp */
|
||||
/********************************************************/
|
||||
/* Initial */
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, init, init);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 1, "uint32_t");
|
||||
/* The pointer to the struct sctp_nets * changing */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 2, "uintptr_t");
|
||||
/* The old value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 3, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 4, "int");
|
||||
|
||||
|
||||
/* ACK-INCREASE */
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, ack, ack);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 1, "uint32_t");
|
||||
/* The pointer to the struct sctp_nets * changing */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 2, "uintptr_t");
|
||||
/* The old value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 3, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 4, "int");
|
||||
|
||||
|
||||
/* ACK-INCREASE */
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, rttvar, rttvar);
|
||||
/* The Vtag << 32 | localport << 16 | remoteport */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 0, "uint64_t");
|
||||
/* obw | nbw */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 1, "uint64_t");
|
||||
/* bwrtt | newrtt */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 2, "uint64_t");
|
||||
/* flight */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 3, "uint64_t");
|
||||
/* (cwnd << 32) | point << 16 | retval(0/1) */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 4, "uint64_t");
|
||||
|
||||
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, rttstep, rttstep);
|
||||
/* The Vtag << 32 | localport << 16 | remoteport */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 0, "uint64_t");
|
||||
/* obw | nbw */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 1, "uint64_t");
|
||||
/* bwrtt | nrtt */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 2, "uint64_t");
|
||||
/* cwnd_saved | stepcnt << 16 | oldstep */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 3, "uint64_t");
|
||||
/* (cwnd << 32) | point << 16 | retval(0/1) */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 4, "uint64_t");
|
||||
|
||||
|
||||
/* FastRetransmit-DECREASE */
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, fr, fr);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 1, "uint32_t");
|
||||
/* The pointer to the struct sctp_nets * changing */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 2, "uintptr_t");
|
||||
/* The old value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 3, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 4, "int");
|
||||
|
||||
|
||||
/* TimeOut-DECREASE */
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, to, to);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 1, "uint32_t");
|
||||
/* The pointer to the struct sctp_nets * changing */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 2, "uintptr_t");
|
||||
/* The old value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 3, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 4, "int");
|
||||
|
||||
|
||||
/* BurstLimit-DECREASE */
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, bl, bl);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 1, "uint32_t");
|
||||
/* The pointer to the struct sctp_nets * changing */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 2, "uintptr_t");
|
||||
/* The old value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 3, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 4, "int");
|
||||
|
||||
|
||||
/* ECN-DECREASE */
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, ecn, ecn);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 1, "uint32_t");
|
||||
/* The pointer to the struct sctp_nets * changing */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 2, "uintptr_t");
|
||||
/* The old value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 3, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 4, "int");
|
||||
|
||||
|
||||
/* PacketDrop-DECREASE */
|
||||
SDT_PROBE_DEFINE(sctp, cwnd, net, pd, pd);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 1, "uint32_t");
|
||||
/* The pointer to the struct sctp_nets * changing */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 2, "uintptr_t");
|
||||
/* The old value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 3, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 4, "int");
|
||||
|
||||
|
||||
|
||||
/********************************************************/
|
||||
/* Rwnd probe - tracks changes in the receiver window for an assoc */
|
||||
/********************************************************/
|
||||
SDT_PROBE_DEFINE(sctp, rwnd, assoc, val, val);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 1, "uint32_t");
|
||||
/* The up/down amount */
|
||||
SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 2, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 3, "int");
|
||||
|
||||
/********************************************************/
|
||||
/* flight probe - tracks changes in the flight size on a net or assoc */
|
||||
/********************************************************/
|
||||
SDT_PROBE_DEFINE(sctp, flightsize, net, val, val);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 1, "uint32_t");
|
||||
/* The pointer to the struct sctp_nets * changing */
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 2, "uintptr_t");
|
||||
/* The up/down amount */
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 3, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 4, "int");
|
||||
/********************************************************/
|
||||
/* The total flight version */
|
||||
/********************************************************/
|
||||
SDT_PROBE_DEFINE(sctp, flightsize, assoc, val, val);
|
||||
/* The Vtag for this end */
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 0, "uint32_t");
|
||||
/* The port number of the local side << 16 | port number of remote
|
||||
* in network byte order.
|
||||
*/
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 1, "uint32_t");
|
||||
/* The up/down amount */
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 2, "int");
|
||||
/* The new value of the cwnd */
|
||||
SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 3, "int");
|
||||
#else /* to #if Freebsd */
|
||||
/* All other platforms not defining dtrace probes */
|
||||
#ifndef SDT_PROBE
|
||||
#define SDT_PROBE(a, b, c, d, e, f, g, h, i)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,284 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
|
||||
* Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* a) Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* b) Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* c) Neither the name of Cisco Systems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
|
||||
#include <netinet/sctp_constants.h>
|
||||
#ifdef USE_MD5
|
||||
#include <crypto/md5.h>
|
||||
#else
|
||||
#if !defined(__APPLE__) && !defined(__Userspace__)
|
||||
#include <netinet/sctp_sha1.h>
|
||||
#endif
|
||||
#endif /* USE_MD5 */
|
||||
#include <netinet/sctp_hashdriver.h>
|
||||
|
||||
/*
|
||||
* Main driver for SCTP's hashing. passing a two pointers and two lengths,
|
||||
* returning a digest pointer filled. The md5 code was taken directly from
|
||||
* the RFC (2104) so to understand it you may want to go look at the RFC
|
||||
* referenced in the SCTP spec. We did modify this code to either user OURs
|
||||
* implementation of SLA1 or the MD5 that comes from its RFC. SLA1 may have
|
||||
* IPR issues so you need to check in to this if you wish to use it... Or at
|
||||
* least that is what the FIP-180.1 web page says.
|
||||
*/
|
||||
|
||||
void
|
||||
sctp_hash_digest(char *key, int key_len, char *text, int text_len,
|
||||
unsigned char *digest)
|
||||
{
|
||||
#ifdef USE_MD5
|
||||
md5_ctxt context;
|
||||
|
||||
#else
|
||||
#if defined(__APPLE__) || defined(__Userspace__)
|
||||
SHA1_CTX context;
|
||||
#else
|
||||
struct sha1_context context;
|
||||
#endif
|
||||
|
||||
#endif /* USE_MD5 */
|
||||
/* inner padding - key XORd with ipad */
|
||||
unsigned char k_ipad[65];
|
||||
|
||||
/* outer padding - key XORd with opad */
|
||||
unsigned char k_opad[65];
|
||||
unsigned char tk[20];
|
||||
int i;
|
||||
|
||||
if (key_len > 64) {
|
||||
#ifdef USE_MD5
|
||||
md5_ctxt tctx;
|
||||
|
||||
MD5Init(&tctx);
|
||||
MD5Update(&tctx, key, key_len);
|
||||
MD5Final(tk, &tctx);
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
#else
|
||||
#if defined(__APPLE__) || defined(__Userspace__)
|
||||
SHA1_CTX tctx;
|
||||
#else
|
||||
struct sha1_context tctx;
|
||||
#endif
|
||||
|
||||
SHA1_Init(&tctx);
|
||||
SHA1_Update(&tctx, (unsigned char *)key, key_len);
|
||||
SHA1_Final(tk, &tctx);
|
||||
key = (char *)tk;
|
||||
key_len = 20;
|
||||
#endif /* USE_MD5 */
|
||||
}
|
||||
/*
|
||||
* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times and text is the data
|
||||
* being protected
|
||||
*/
|
||||
|
||||
/* start out by storing key in pads */
|
||||
bzero(k_ipad, sizeof k_ipad);
|
||||
bzero(k_opad, sizeof k_opad);
|
||||
bcopy(key, k_ipad, key_len);
|
||||
bcopy(key, k_opad, key_len);
|
||||
|
||||
/* XOR key with ipad and opad values */
|
||||
for (i = 0; i < 64; i++) {
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
/*
|
||||
* perform inner MD5
|
||||
*/
|
||||
#ifdef USE_MD5
|
||||
MD5Init(&context); /* init context for 1st pass */
|
||||
MD5Update(&context, k_ipad, 64); /* start with inner pad */
|
||||
MD5Update(&context, text, text_len); /* then text of datagram */
|
||||
MD5Final(digest, &context); /* finish up 1st pass */
|
||||
#else
|
||||
SHA1_Init(&context); /* init context for 1st pass */
|
||||
SHA1_Update(&context, k_ipad, 64); /* start with inner pad */
|
||||
SHA1_Update(&context,
|
||||
(unsigned char *)text,
|
||||
text_len); /* then text of datagram */
|
||||
SHA1_Final(digest, &context); /* finish up 1st pass */
|
||||
#endif /* USE_MD5 */
|
||||
|
||||
/*
|
||||
* perform outer MD5
|
||||
*/
|
||||
#ifdef USE_MD5
|
||||
MD5Init(&context); /* init context for 2nd pass */
|
||||
MD5Update(&context, k_opad, 64); /* start with outer pad */
|
||||
MD5Update(&context, digest, 16); /* then results of 1st hash */
|
||||
MD5Final(digest, &context); /* finish up 2nd pass */
|
||||
#else
|
||||
SHA1_Init(&context); /* init context for 2nd pass */
|
||||
SHA1_Update(&context, k_opad, 64); /* start with outer pad */
|
||||
SHA1_Update(&context,
|
||||
(unsigned char *)digest, 20); /* then results of 1st hash */
|
||||
SHA1_Final(digest, &context); /* finish up 2nd pass */
|
||||
#endif /* USE_MD5 */
|
||||
}
|
||||
|
||||
void
|
||||
sctp_hash_digest_m(char *key, int key_len, struct mbuf *m, int offset,
|
||||
unsigned char *digest)
|
||||
{
|
||||
struct mbuf *m_at;
|
||||
|
||||
#ifdef USE_MD5
|
||||
md5_ctxt context;
|
||||
|
||||
#else
|
||||
#if defined(__APPLE__) || defined(__Userspace__)
|
||||
SHA1_CTX context;
|
||||
#else
|
||||
struct sha1_context context;
|
||||
#endif
|
||||
|
||||
#endif /* USE_MD5 */
|
||||
/* inner padding - key XORd with ipad */
|
||||
unsigned char k_ipad[65];
|
||||
|
||||
/* outer padding - key XORd with opad */
|
||||
unsigned char k_opad[65];
|
||||
unsigned char tk[20];
|
||||
int i;
|
||||
|
||||
if (key_len > 64) {
|
||||
#ifdef USE_MD5
|
||||
md5_ctxt tctx;
|
||||
|
||||
MD5Init(&tctx);
|
||||
MD5Update(&tctx, key, key_len);
|
||||
MD5Final(tk, &tctx);
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
#else
|
||||
#if defined(__APPLE__) || defined(__Userspace__)
|
||||
SHA1_CTX tctx;
|
||||
#else
|
||||
struct sha1_context tctx;
|
||||
#endif
|
||||
|
||||
SHA1_Init(&tctx);
|
||||
SHA1_Update(&tctx, (unsigned char *)key, key_len);
|
||||
SHA1_Final(tk, &tctx);
|
||||
key = (char *)tk;
|
||||
key_len = 20;
|
||||
#endif /* USE_MD5 */
|
||||
}
|
||||
/*
|
||||
* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times and text is the data
|
||||
* being protected
|
||||
*/
|
||||
|
||||
/* start out by storing key in pads */
|
||||
bzero(k_ipad, sizeof k_ipad);
|
||||
bzero(k_opad, sizeof k_opad);
|
||||
bcopy(key, k_ipad, key_len);
|
||||
bcopy(key, k_opad, key_len);
|
||||
|
||||
/* XOR key with ipad and opad values */
|
||||
for (i = 0; i < 64; i++) {
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
|
||||
/* find the correct mbuf and offset into mbuf */
|
||||
m_at = m;
|
||||
while ((m_at != NULL) && (offset > SCTP_BUF_LEN(m_at))) {
|
||||
offset -= SCTP_BUF_LEN(m_at); /* update remaining offset left */
|
||||
m_at = SCTP_BUF_NEXT(m_at);
|
||||
}
|
||||
/*
|
||||
* perform inner MD5
|
||||
*/
|
||||
#ifdef USE_MD5
|
||||
MD5Init(&context); /* init context for 1st pass */
|
||||
MD5Update(&context, k_ipad, 64); /* start with inner pad */
|
||||
/******/
|
||||
while (m_at != NULL) {
|
||||
/* then text of datagram... */
|
||||
MD5Update(&context, mtod(m_at, char *)+offset,
|
||||
SCTP_BUF_LEN(m_at) - offset);
|
||||
/* only offset on the first mbuf */
|
||||
offset = 0;
|
||||
m_at = SCTP_BUF_NEXT(m_at);
|
||||
}
|
||||
/******/
|
||||
MD5Final(digest, &context); /* finish up 1st pass */
|
||||
#else
|
||||
SHA1_Init(&context); /* init context for 1st pass */
|
||||
SHA1_Update(&context, k_ipad, 64); /* start with inner pad */
|
||||
/******/
|
||||
while (m_at != NULL) {
|
||||
/* then text of datagram */
|
||||
SHA1_Update(&context, mtod(m_at, unsigned char *)+offset,
|
||||
SCTP_BUF_LEN(m_at) - offset);
|
||||
/* only offset on the first mbuf */
|
||||
offset = 0;
|
||||
m_at = SCTP_BUF_NEXT(m_at);
|
||||
}
|
||||
/******/
|
||||
SHA1_Final(digest, &context); /* finish up 1st pass */
|
||||
#endif /* USE_MD5 */
|
||||
|
||||
/*
|
||||
* perform outer MD5
|
||||
*/
|
||||
#ifdef USE_MD5
|
||||
MD5Init(&context); /* init context for 2nd pass */
|
||||
MD5Update(&context, k_opad, 64); /* start with outer pad */
|
||||
MD5Update(&context, digest, 16); /* then results of 1st hash */
|
||||
MD5Final(digest, &context); /* finish up 2nd pass */
|
||||
#else
|
||||
SHA1_Init(&context); /* init context for 2nd pass */
|
||||
SHA1_Update(&context, k_opad, 64); /* start with outer pad */
|
||||
SHA1_Update(&context, digest, 20); /* then results of 1st hash */
|
||||
SHA1_Final(digest, &context); /* finish up 2nd pass */
|
||||
#endif /* USE_MD5 */
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
|
||||
* Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* a) Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* b) Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* c) Neither the name of Cisco Systems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_HASHDRIVER_H_
|
||||
#define _NETINET_SCTP_HASHDRIVER_H_
|
||||
|
||||
|
||||
void sctp_hash_digest(char *, int, char *, int, unsigned char *);
|
||||
|
||||
void sctp_hash_digest_m(char *, int, struct mbuf *, int, unsigned char *);
|
||||
|
||||
#endif
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 246674 2013-02-11 13:57:03Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 258228 2013-11-16 16:09:09Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -806,13 +806,12 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc)
|
||||
* but should we?
|
||||
*/
|
||||
if (stcb->sctp_socket) {
|
||||
pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket),
|
||||
pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
|
||||
stcb->sctp_ep->partial_delivery_point);
|
||||
} else {
|
||||
pd_point = stcb->sctp_ep->partial_delivery_point;
|
||||
}
|
||||
if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) {
|
||||
|
||||
/*
|
||||
* Yes, we setup to start reception, by
|
||||
* backing down the TSN just in case we
|
||||
@ -1432,7 +1431,6 @@ sctp_does_tsn_belong_to_reasm(struct sctp_association *asoc,
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
struct mbuf **m, int offset, struct sctp_data_chunk *ch, int chk_length,
|
||||
@ -1742,7 +1740,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
sctp_alloc_a_readq(stcb, control);
|
||||
sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn,
|
||||
protocol_id,
|
||||
stcb->asoc.context,
|
||||
strmno, strmseq,
|
||||
chunk_flags,
|
||||
dmbuf);
|
||||
@ -1804,7 +1801,6 @@ failed_express_del:
|
||||
asoc->highest_tsn_inside_nr_map = tsn;
|
||||
}
|
||||
SCTP_STAT_INCR(sctps_recvexpressm);
|
||||
control->sinfo_tsn = tsn;
|
||||
asoc->tsn_last_delivered = tsn;
|
||||
asoc->fragment_flags = chunk_flags;
|
||||
asoc->tsn_of_pdapi_last_delivered = tsn;
|
||||
@ -1868,7 +1864,6 @@ failed_express_del:
|
||||
sctp_alloc_a_readq(stcb, control);
|
||||
sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn,
|
||||
protocol_id,
|
||||
stcb->asoc.context,
|
||||
strmno, strmseq,
|
||||
chunk_flags,
|
||||
dmbuf);
|
||||
@ -2506,7 +2501,7 @@ sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc)
|
||||
* delivery queue and something can be delivered.
|
||||
*/
|
||||
if (stcb->sctp_socket) {
|
||||
pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket),
|
||||
pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
|
||||
stcb->sctp_ep->partial_delivery_point);
|
||||
} else {
|
||||
pd_point = stcb->sctp_ep->partial_delivery_point;
|
||||
@ -3695,6 +3690,7 @@ sctp_fs_audit(struct sctp_association *asoc)
|
||||
struct sctp_tmit_chunk *chk;
|
||||
int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0;
|
||||
int entry_flight, entry_cnt, ret;
|
||||
|
||||
entry_flight = asoc->total_flight;
|
||||
entry_cnt = asoc->total_flight_count;
|
||||
ret = 0;
|
||||
@ -4743,7 +4739,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
|
||||
}
|
||||
}
|
||||
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
|
||||
if (tp1->pr_sctp_on) {
|
||||
if (PR_SCTP_ENABLED(tp1->flags)) {
|
||||
if (asoc->pr_sctp_cnt != 0)
|
||||
asoc->pr_sctp_cnt--;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.h 237715 2012-06-28 16:01:08Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.h 252585 2013-07-03 18:48:43Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_INDATA_H_
|
||||
@ -49,14 +49,14 @@ sctp_build_readq_entry(struct sctp_tcb *stcb,
|
||||
struct mbuf *dm);
|
||||
|
||||
|
||||
#define sctp_build_readq_entry_mac(_ctl, in_it, a, net, tsn, ppid, context, stream_no, stream_seq, flags, dm) do { \
|
||||
#define sctp_build_readq_entry_mac(_ctl, in_it, context, net, tsn, ppid, stream_no, stream_seq, flags, dm) do { \
|
||||
if (_ctl) { \
|
||||
atomic_add_int(&((net)->ref_count), 1); \
|
||||
(_ctl)->sinfo_stream = stream_no; \
|
||||
(_ctl)->sinfo_ssn = stream_seq; \
|
||||
(_ctl)->sinfo_flags = (flags << 8); \
|
||||
(_ctl)->sinfo_ppid = ppid; \
|
||||
(_ctl)->sinfo_context = a; \
|
||||
(_ctl)->sinfo_context = context; \
|
||||
(_ctl)->sinfo_timetolive = 0; \
|
||||
(_ctl)->sinfo_tsn = tsn; \
|
||||
(_ctl)->sinfo_cumtsn = tsn; \
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 246595 2013-02-09 17:26:14Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 262252 2014-02-20 20:14:43Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -412,9 +412,10 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
|
||||
}
|
||||
SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
|
||||
}
|
||||
asoc->streamincnt = ntohs(init->num_outbound_streams);
|
||||
if (asoc->streamincnt > MAX_SCTP_STREAMS) {
|
||||
asoc->streamincnt = MAX_SCTP_STREAMS;
|
||||
if (asoc->max_inbound_streams > ntohs(init->num_outbound_streams)) {
|
||||
asoc->streamincnt = ntohs(init->num_outbound_streams);
|
||||
} else {
|
||||
asoc->streamincnt = asoc->max_inbound_streams;
|
||||
}
|
||||
SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt *
|
||||
sizeof(struct sctp_stream_in), SCTP_M_STRMI);
|
||||
@ -426,11 +427,6 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
|
||||
for (i = 0; i < asoc->streamincnt; i++) {
|
||||
asoc->strmin[i].stream_no = i;
|
||||
asoc->strmin[i].last_sequence_delivered = 0xffff;
|
||||
/*
|
||||
* U-stream ranges will be set when the cookie is unpacked.
|
||||
* Or for the INIT sender they are un set (if pr-sctp not
|
||||
* supported) when the INIT-ACK arrives.
|
||||
*/
|
||||
TAILQ_INIT(&asoc->strmin[i].inqueue);
|
||||
asoc->strmin[i].delivery_started = 0;
|
||||
}
|
||||
@ -468,7 +464,6 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
|
||||
|
||||
/* First verify that we have no illegal param's */
|
||||
abort_flag = 0;
|
||||
op_err = NULL;
|
||||
|
||||
op_err = sctp_arethere_unrecognized_parameters(m,
|
||||
(offset + sizeof(struct sctp_init_chunk)),
|
||||
@ -1068,12 +1063,13 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
#endif
|
||||
}
|
||||
/* are the queues empty? */
|
||||
#ifdef INVARIANTS
|
||||
if (!TAILQ_EMPTY(&asoc->send_queue) ||
|
||||
!TAILQ_EMPTY(&asoc->sent_queue) ||
|
||||
!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
|
||||
sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED);
|
||||
panic("Queues are not empty when handling SHUTDOWN-ACK");
|
||||
}
|
||||
#endif
|
||||
/* stop the timer */
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_9);
|
||||
/* send SHUTDOWN-COMPLETE */
|
||||
@ -1614,7 +1610,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
return (NULL);
|
||||
|
||||
}
|
||||
switch SCTP_GET_STATE(asoc) {
|
||||
switch (SCTP_GET_STATE(asoc)) {
|
||||
case SCTP_STATE_COOKIE_WAIT:
|
||||
case SCTP_STATE_COOKIE_ECHOED:
|
||||
/*
|
||||
@ -1926,20 +1922,24 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce &&
|
||||
cookie->tie_tag_peer_vtag != 0) {
|
||||
struct sctpasochead *head;
|
||||
if (asoc->peer_supports_nat) {
|
||||
/* This is a gross gross hack.
|
||||
* just call the cookie_new code since we
|
||||
* are allowing a duplicate association. I hope
|
||||
* this works...
|
||||
*/
|
||||
return (sctp_process_cookie_new(m, iphlen, offset, src, dst,
|
||||
sh, cookie, cookie_len,
|
||||
inp, netp, init_src,notification,
|
||||
auth_skipped, auth_offset, auth_len,
|
||||
#if defined(__FreeBSD__)
|
||||
use_mflowid, mflowid,
|
||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
struct socket *so;
|
||||
#endif
|
||||
vrf_id, port));
|
||||
|
||||
if (asoc->peer_supports_nat) {
|
||||
/* This is a gross gross hack.
|
||||
* Just call the cookie_new code since we
|
||||
* are allowing a duplicate association.
|
||||
* I hope this works...
|
||||
*/
|
||||
return (sctp_process_cookie_new(m, iphlen, offset, src, dst,
|
||||
sh, cookie, cookie_len,
|
||||
inp, netp, init_src,notification,
|
||||
auth_skipped, auth_offset, auth_len,
|
||||
#if defined(__FreeBSD__)
|
||||
use_mflowid, mflowid,
|
||||
#endif
|
||||
vrf_id, port));
|
||||
}
|
||||
/*
|
||||
* case A in Section 5.2.4 Table 2: XXMM (peer restarted)
|
||||
@ -1992,6 +1992,10 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
asoc->mapping_array_size);
|
||||
}
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
so = SCTP_INP_SO(stcb->sctp_ep);
|
||||
SCTP_SOCKET_LOCK(so, 1);
|
||||
#endif
|
||||
SCTP_INP_INFO_WLOCK();
|
||||
SCTP_INP_WLOCK(stcb->sctp_ep);
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
@ -1999,7 +2003,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
/* send up all the data */
|
||||
SCTP_TCB_SEND_LOCK(stcb);
|
||||
|
||||
sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_NOT_LOCKED);
|
||||
sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED);
|
||||
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
|
||||
stcb->asoc.strmout[i].chunks_on_queues = 0;
|
||||
stcb->asoc.strmout[i].stream_no = i;
|
||||
@ -2021,11 +2025,15 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
*/
|
||||
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
|
||||
|
||||
/* process the INIT info (peer's info) */
|
||||
SCTP_TCB_SEND_UNLOCK(stcb);
|
||||
SCTP_INP_WUNLOCK(stcb->sctp_ep);
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
|
||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
#endif
|
||||
asoc->total_flight = 0;
|
||||
asoc->total_flight_count = 0;
|
||||
/* process the INIT info (peer's info) */
|
||||
retval = sctp_process_init(init_cp, stcb);
|
||||
if (retval < 0) {
|
||||
if (how_indx < sizeof(asoc->cookie_how))
|
||||
@ -3335,13 +3343,14 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE
|
||||
/* notify upper layer protocol */
|
||||
if (stcb->sctp_socket) {
|
||||
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
|
||||
/* are the queues empty? they should be */
|
||||
if (!TAILQ_EMPTY(&asoc->send_queue) ||
|
||||
!TAILQ_EMPTY(&asoc->sent_queue) ||
|
||||
!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
|
||||
sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED);
|
||||
}
|
||||
}
|
||||
#ifdef INVARIANTS
|
||||
if (!TAILQ_EMPTY(&asoc->send_queue) ||
|
||||
!TAILQ_EMPTY(&asoc->sent_queue) ||
|
||||
!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
|
||||
panic("Queues are not empty when handling SHUTDOWN-COMPLETE");
|
||||
}
|
||||
#endif
|
||||
/* stop the timer */
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_22);
|
||||
SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
|
||||
@ -3599,7 +3608,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
|
||||
}
|
||||
|
||||
void
|
||||
sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list)
|
||||
sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list)
|
||||
{
|
||||
uint32_t i;
|
||||
uint16_t temp;
|
||||
@ -3627,18 +3636,13 @@ sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *
|
||||
}
|
||||
|
||||
static void
|
||||
sctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * list)
|
||||
sctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list)
|
||||
{
|
||||
int i;
|
||||
uint32_t i;
|
||||
uint16_t temp;
|
||||
|
||||
if (number_entries == 0) {
|
||||
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
|
||||
stcb->asoc.strmout[i].next_sequence_send = 0;
|
||||
}
|
||||
} else if (number_entries) {
|
||||
if (number_entries > 0) {
|
||||
for (i = 0; i < number_entries; i++) {
|
||||
uint16_t temp;
|
||||
|
||||
temp = ntohs(list[i]);
|
||||
if (temp >= stcb->asoc.streamoutcnt) {
|
||||
/* no such stream */
|
||||
@ -3646,6 +3650,10 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * lis
|
||||
}
|
||||
stcb->asoc.strmout[temp].next_sequence_send = 0;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
|
||||
stcb->asoc.strmout[i].next_sequence_send = 0;
|
||||
}
|
||||
}
|
||||
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
|
||||
}
|
||||
@ -3732,7 +3740,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
|
||||
struct sctp_association *asoc = &stcb->asoc;
|
||||
struct sctp_tmit_chunk *chk;
|
||||
struct sctp_stream_reset_out_request *srparam;
|
||||
int number_entries;
|
||||
uint32_t number_entries;
|
||||
|
||||
if (asoc->stream_reset_outstanding == 0) {
|
||||
/* duplicate */
|
||||
@ -4079,7 +4087,7 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
|
||||
if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
|
||||
asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
|
||||
} else if ((num_stream > stcb->asoc.max_inbound_streams) ||
|
||||
(num_stream > 0xffff)) {
|
||||
(num_stream > 0xffff)) {
|
||||
/* We must reject it they ask for to many */
|
||||
denied:
|
||||
stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
|
||||
@ -4691,8 +4699,10 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
|
||||
if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) ||
|
||||
(ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) ||
|
||||
(ch->chunk_type == SCTP_PACKET_DROPPED)) {
|
||||
if ((vtag_in == asoc->my_vtag) ||
|
||||
((ch->chunk_flags & SCTP_HAD_NO_TCB) &&
|
||||
/* Take the T-bit always into account. */
|
||||
if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) &&
|
||||
(vtag_in == asoc->my_vtag)) ||
|
||||
(((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) &&
|
||||
(vtag_in == asoc->peer_vtag))) {
|
||||
/* this is valid */
|
||||
} else {
|
||||
@ -5704,6 +5714,7 @@ sctp_validate_no_locks(struct sctp_inpcb *inp)
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
struct sctp_tcb *lstcb;
|
||||
|
||||
LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) {
|
||||
if (mtx_owned(&lstcb->tcb_mtx)) {
|
||||
panic("Own lock on stcb at return from input");
|
||||
@ -5853,7 +5864,11 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (ipsec4_in_reject(m, &inp->ip_inp.inp)) {
|
||||
#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036)
|
||||
IPSECSTAT_INC(ips_in_polvio);
|
||||
#else
|
||||
MODULE_GLOBAL(ipsec4stat).in_polvio++;
|
||||
#endif
|
||||
SCTP_STAT_INCR(sctps_hdrops);
|
||||
goto out;
|
||||
}
|
||||
@ -5862,7 +5877,11 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (ipsec6_in_reject(m, &inp->ip_inp.inp)) {
|
||||
#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036)
|
||||
IPSEC6STAT_INC(ips_in_polvio);
|
||||
#else
|
||||
MODULE_GLOBAL(ipsec6stat).in_polvio++;
|
||||
#endif
|
||||
SCTP_STAT_INCR(sctps_hdrops);
|
||||
goto out;
|
||||
}
|
||||
@ -6209,7 +6228,13 @@ sctp_input(i_pak, va_alist)
|
||||
}
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
#if __FreeBSD_version >= 800000
|
||||
#if __FreeBSD_version > 1000049
|
||||
SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
|
||||
"sctp_input(): Packet of length %d received on %s with csum_flags 0x%b.\n",
|
||||
m->m_pkthdr.len,
|
||||
if_name(m->m_pkthdr.rcvif),
|
||||
(int)m->m_pkthdr.csum_flags, CSUM_BITS);
|
||||
#elif __FreeBSD_version >= 800000
|
||||
SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
|
||||
"sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
|
||||
m->m_pkthdr.len,
|
||||
|
@ -44,8 +44,6 @@
|
||||
#if defined(__Userspace_os_Windows)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <ws2ipdef.h>
|
||||
#include <ws2def.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <Mswsock.h>
|
||||
#include <Windows.h>
|
||||
@ -63,6 +61,10 @@ typedef struct
|
||||
CRITICAL_SECTION waiters_count_lock;
|
||||
HANDLE events_[C_MAX_EVENTS];
|
||||
} userland_cond_t;
|
||||
void InitializeXPConditionVariable(userland_cond_t *);
|
||||
void DeleteXPConditionVariable(userland_cond_t *);
|
||||
int SleepXPConditionVariable(userland_cond_t *, userland_mutex_t *);
|
||||
void WakeAllXPConditionVariable(userland_cond_t *);
|
||||
#define InitializeConditionVariable(cond) InitializeXPConditionVariable(cond)
|
||||
#define DeleteConditionVariable(cond) DeleteXPConditionVariable(cond)
|
||||
#define SleepConditionVariableCS(cond, mtx, time) SleepXPConditionVariable(cond, mtx)
|
||||
@ -75,27 +77,32 @@ typedef HANDLE userland_thread_t;
|
||||
#define ADDRESS_FAMILY unsigned __int8
|
||||
#define IPVERSION 4
|
||||
#define MAXTTL 255
|
||||
/* VS2010 comes with stdint.h */
|
||||
#if _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#define uint64_t unsigned __int64
|
||||
#define uint32_t unsigned __int32
|
||||
#define int32_t __int32
|
||||
#define uint16_t unsigned __int16
|
||||
#define int16_t __int16
|
||||
#define uint8_t unsigned __int8
|
||||
#define int8_t __int8
|
||||
#endif
|
||||
#ifndef _SIZE_T_DEFINED
|
||||
#define size_t __int32
|
||||
#endif
|
||||
#define u_long unsigned __int64
|
||||
#define u_int unsigned __int32
|
||||
#define uint32_t unsigned __int32
|
||||
#define u_int32_t unsigned __int32
|
||||
#define int32_t __int32
|
||||
#define int16_t __int16
|
||||
#define uint16_t unsigned __int16
|
||||
#define u_int16_t unsigned __int16
|
||||
#define uint8_t unsigned __int8
|
||||
#define u_int8_t unsigned __int8
|
||||
#define int8_t __int8
|
||||
#define u_char unsigned char
|
||||
#define n_short unsigned __int16
|
||||
#define u_short unsigned __int16
|
||||
#define ssize_t __int64
|
||||
#define size_t __int32
|
||||
#define in_addr_t unsigned __int32
|
||||
#define in_port_t unsigned __int16
|
||||
#define n_time unsigned __int32
|
||||
#define sa_family_t unsigned __int8
|
||||
#define ssize_t __int64
|
||||
#define IFNAMSIZ 64
|
||||
#define __func__ __FUNCTION__
|
||||
|
||||
@ -210,8 +217,10 @@ typedef HANDLE userland_thread_t;
|
||||
|
||||
typedef char* caddr_t;
|
||||
|
||||
int Win_getifaddrs(struct ifaddrs**);
|
||||
#define getifaddrs(interfaces) (int)Win_getifaddrs(interfaces)
|
||||
#define if_nametoindex(x) (int)win_if_nametoindex(x)
|
||||
int win_if_nametoindex(const char *);
|
||||
#define if_nametoindex(x) win_if_nametoindex(x)
|
||||
|
||||
#define bzero(buf, len) memset(buf, 0, len)
|
||||
#define bcopy(srcKey, dstKey, len) memcpy(dstKey, srcKey, len)
|
||||
@ -226,12 +235,22 @@ typedef char* caddr_t;
|
||||
#ifdef CMSG_DATA
|
||||
#undef CMSG_DATA
|
||||
#endif
|
||||
/*
|
||||
* The following definitions should apply iff WINVER < 0x0600
|
||||
* but that check doesn't work in all cases. So be more pedantic...
|
||||
*/
|
||||
#define CMSG_DATA(x) WSA_CMSG_DATA(x)
|
||||
#define CMSG_ALIGN(x) WSA_CMSGDATA_ALIGN(x)
|
||||
#if WINVER < 0x0600
|
||||
#ifndef CMSG_FIRSTHDR
|
||||
#define CMSG_FIRSTHDR(x) WSA_CMSG_FIRSTHDR(x)
|
||||
#endif
|
||||
#ifndef CMSG_NXTHDR
|
||||
#define CMSG_NXTHDR(x, y) WSA_CMSG_NXTHDR(x, y)
|
||||
#endif
|
||||
#ifndef CMSG_SPACE
|
||||
#define CMSG_SPACE(x) WSA_CMSG_SPACE(x)
|
||||
#endif
|
||||
#ifndef CMSG_LEN
|
||||
#define CMSG_LEN(x) WSA_CMSG_LEN(x)
|
||||
#endif
|
||||
|
||||
@ -383,7 +402,7 @@ struct udphdr {
|
||||
#else /* !defined(Userspace_os_Windows) */
|
||||
#include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */
|
||||
#include <sys/socket.h>
|
||||
#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined(ANDROID)
|
||||
#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(ANDROID)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
typedef pthread_mutex_t userland_mutex_t;
|
||||
@ -397,7 +416,9 @@ typedef pthread_t userland_thread_t;
|
||||
#define MA_OWNED 7 /* sys/mutex.h typically on FreeBSD */
|
||||
#if !defined(__Userspace_os_FreeBSD)
|
||||
struct mtx {int dummy;};
|
||||
#if !defined(__Userspace_os_NetBSD)
|
||||
struct selinfo {int dummy;};
|
||||
#endif
|
||||
struct sx {int dummy;};
|
||||
#endif
|
||||
|
||||
@ -463,7 +484,7 @@ struct sx {int dummy;};
|
||||
/* for getifaddrs */
|
||||
#include <sys/types.h>
|
||||
#if !defined(__Userspace_os_Windows)
|
||||
#if !defined(ANDROID)
|
||||
#if !defined(ANDROID) && (defined(INET) || defined(INET6))
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
@ -500,7 +521,7 @@ struct sx {int dummy;};
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#endif
|
||||
#if defined(__Userspace_os_Linux) || defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) ||defined(__Userspace_os_Windows)
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_Windows)
|
||||
#include "user_ip6_var.h"
|
||||
#else
|
||||
#include <netinet6/ip6_var.h>
|
||||
@ -518,6 +539,8 @@ struct sx {int dummy;};
|
||||
#include <sys/filedesc.h>
|
||||
#endif
|
||||
|
||||
#include "netinet/sctp_sha1.h"
|
||||
|
||||
#if __FreeBSD_version >= 700000
|
||||
#include <netinet/ip_options.h>
|
||||
#endif
|
||||
@ -582,21 +605,21 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
|
||||
|
||||
#if defined(SCTP_DEBUG)
|
||||
#include <netinet/sctp_constants.h>
|
||||
#define SCTPDBG(level, ...) \
|
||||
{ \
|
||||
do { \
|
||||
if (SCTP_BASE_SYSCTL(sctp_debug_on) & level) { \
|
||||
SCTP_PRINTF(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0); \
|
||||
#define SCTPDBG(level, ...) \
|
||||
{ \
|
||||
do { \
|
||||
if (SCTP_BASE_SYSCTL(sctp_debug_on) & level) { \
|
||||
SCTP_PRINTF(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0); \
|
||||
}
|
||||
#define SCTPDBG_ADDR(level, addr) \
|
||||
{ \
|
||||
do { \
|
||||
if (SCTP_BASE_SYSCTL(sctp_debug_on) & level ) { \
|
||||
sctp_print_address(addr); \
|
||||
} \
|
||||
} while (0); \
|
||||
#define SCTPDBG_ADDR(level, addr) \
|
||||
{ \
|
||||
do { \
|
||||
if (SCTP_BASE_SYSCTL(sctp_debug_on) & level ) { \
|
||||
sctp_print_address(addr); \
|
||||
} \
|
||||
} while (0); \
|
||||
}
|
||||
#else
|
||||
#define SCTPDBG(level, ...)
|
||||
@ -654,17 +677,17 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
|
||||
/*
|
||||
* general memory allocation
|
||||
*/
|
||||
#define SCTP_MALLOC(var, type, size, name) \
|
||||
do { \
|
||||
MALLOC(var, type, size, name, M_NOWAIT); \
|
||||
} while (0)
|
||||
#define SCTP_MALLOC(var, type, size, name) \
|
||||
do { \
|
||||
MALLOC(var, type, size, name, M_NOWAIT); \
|
||||
} while (0)
|
||||
|
||||
#define SCTP_FREE(var, type) FREE(var, type)
|
||||
|
||||
#define SCTP_MALLOC_SONAME(var, type, size) \
|
||||
do { \
|
||||
MALLOC(var, type, size, M_SONAME, (M_WAITOK | M_ZERO)); \
|
||||
} while (0)
|
||||
#define SCTP_MALLOC_SONAME(var, type, size) \
|
||||
do { \
|
||||
MALLOC(var, type, size, M_SONAME, (M_WAITOK | M_ZERO)); \
|
||||
} while (0)
|
||||
|
||||
#define SCTP_FREE_SONAME(var) FREE(var, M_SONAME)
|
||||
|
||||
@ -978,72 +1001,18 @@ int sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af);
|
||||
/* This is re-pulse ourselves for sendbuf */
|
||||
#define SCTP_ZERO_COPY_SENDQ_EVENT(inp, so)
|
||||
|
||||
|
||||
/*
|
||||
* SCTP AUTH
|
||||
*/
|
||||
/* USE_SCTP_SHA1 is defined if you need sctp_sha1.[ch]. SHA1_* functions are defined
|
||||
* there. On Linux, they are also defined in libcrypto.a once you install
|
||||
* the libssl-dev package (on Ubuntu, at least).
|
||||
*/
|
||||
/* #define USE_SCTP_SHA1 */
|
||||
|
||||
/* #define HAVE_SHA2 sha2.h exists on Linux? */
|
||||
|
||||
|
||||
#define SCTP_READ_RANDOM(buf, len) read_random(buf, len)
|
||||
|
||||
|
||||
#ifdef USE_SCTP_SHA1
|
||||
#include <netinet/sctp_sha1.h>
|
||||
#else
|
||||
#if 0 /*this was old _KERNEL code... */
|
||||
#include <crypto/sha1.h>
|
||||
/* map standard crypto API names */
|
||||
#define SHA1_Init SHA1Init
|
||||
#define SHA1_Update SHA1Update
|
||||
#define SHA1_Final(x,y) SHA1Final((caddr_t)x, y)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SHA2)
|
||||
#include <crypto/sha2/sha2.h>
|
||||
#endif
|
||||
#if 0
|
||||
/* going to have to port so generic across OS's... */
|
||||
#if 1 /* openssl header files on FreeBSD 6.3 on Emulab and libssl-dev for Ubuntu */
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
/* libssl-dev calls this SHA_CTX, but it's refered to as SHA1_CTX within the
|
||||
* SCTP stack code so here we typedef (or macro?) to equate the two.
|
||||
*/
|
||||
typedef SHA_CTX SHA1_CTX;
|
||||
|
||||
#else /* only _KERNEL? */
|
||||
|
||||
#include <sys/md5.h>
|
||||
/* map standard crypto API names */
|
||||
#define MD5_Init MD5Init
|
||||
#define MD5_Update MD5Update
|
||||
#define MD5_Final MD5Final
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define SCTP_SHA1_CTX struct sctp_sha1_context
|
||||
#define SCTP_SHA1_INIT sctp_sha1_init
|
||||
#define SCTP_SHA1_UPDATE sctp_sha1_update
|
||||
#define SCTP_SHA1_FINAL(x,y) sctp_sha1_final((unsigned char *)x, y)
|
||||
|
||||
/* start OOTB only stuff */
|
||||
|
||||
|
||||
/* TODO IFT_LOOP is in net/if_types.h on Linux */
|
||||
#define IFT_LOOP 0x18
|
||||
|
||||
/* sctp_pcb.h */
|
||||
/* typedef int SHA1_CTX; */
|
||||
/* typedef int MD5_CTX; */
|
||||
#ifdef HAVE_SHA2
|
||||
typedef int SHA256_CTX;
|
||||
typedef int SHA384_CTX;
|
||||
typedef int SHA512_CTX;
|
||||
#endif
|
||||
|
||||
#if defined(__Userspace_os_Windows)
|
||||
#define SHUT_RD 1
|
||||
@ -1070,6 +1039,11 @@ struct sockaddr_conn {
|
||||
void *sconn_addr;
|
||||
};
|
||||
|
||||
/*
|
||||
* SCTP protocol specific mbuf flags.
|
||||
*/
|
||||
#define M_NOTIFICATION M_PROTO5 /* SCTP notification */
|
||||
|
||||
/*
|
||||
* IP output routines
|
||||
*/
|
||||
@ -1117,9 +1091,11 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int a
|
||||
/* with the current included files, this is defined in Linux but
|
||||
* in FreeBSD, it is behind a _KERNEL in sys/socket.h ...
|
||||
*/
|
||||
#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD)
|
||||
#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD)
|
||||
/* stolen from /usr/include/sys/socket.h */
|
||||
#define CMSG_ALIGN(n) _ALIGN(n)
|
||||
#elif defined(__Userspace_os_NetBSD)
|
||||
#define CMSG_ALIGN(n) (((n) + __ALIGNBYTES) & ~__ALIGNBYTES)
|
||||
#elif defined(__Userspace_os_Darwin)
|
||||
#if !defined(__DARWIN_ALIGNBYTES)
|
||||
#define __DARWIN_ALIGNBYTES (sizeof(__darwin_size_t) - 1)
|
||||
@ -1156,14 +1132,21 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int a
|
||||
#endif
|
||||
|
||||
#if defined(__Userspace_os_Linux)
|
||||
#if !defined(TAILQ_FOREACH_SAFE)
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((head)->tqh_first); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#endif
|
||||
#if !defined(LIST_FOREACH_SAFE)
|
||||
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((head)->lh_first); \
|
||||
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__Userspace_os_DragonFly)
|
||||
#define TAILQ_FOREACH_SAFE TAILQ_FOREACH_MUTABLE
|
||||
#define LIST_FOREACH_SAFE LIST_FOREACH_MUTABLE
|
||||
#endif
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 246687 2013-02-11 21:02:49Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 262252 2014-02-20 20:14:43Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -1972,9 +1972,11 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa,
|
||||
static struct mbuf *
|
||||
sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len)
|
||||
{
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct sctp_paramhdr *parmh;
|
||||
struct mbuf *mret;
|
||||
uint16_t plen;
|
||||
#endif
|
||||
|
||||
switch (ifa->address.sa.sa_family) {
|
||||
#ifdef INET
|
||||
@ -1990,6 +1992,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len)
|
||||
default:
|
||||
return (m);
|
||||
}
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (M_TRAILINGSPACE(m) >= plen) {
|
||||
/* easy side we just drop it on the end */
|
||||
parmh = (struct sctp_paramhdr *)(SCTP_BUF_AT(m, SCTP_BUF_LEN(m)));
|
||||
@ -2052,6 +2055,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len)
|
||||
*len += plen;
|
||||
}
|
||||
return (mret);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -3446,7 +3450,11 @@ sctp_find_cmsg(int c_type, void *data, struct mbuf *control, size_t cpsize)
|
||||
return (found);
|
||||
}
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_prinfo), (caddr_t)&prinfo);
|
||||
sndrcvinfo->sinfo_timetolive = prinfo.pr_value;
|
||||
if (prinfo.pr_policy != SCTP_PR_SCTP_NONE) {
|
||||
sndrcvinfo->sinfo_timetolive = prinfo.pr_value;
|
||||
} else {
|
||||
sndrcvinfo->sinfo_timetolive = 0;
|
||||
}
|
||||
sndrcvinfo->sinfo_flags |= prinfo.pr_policy;
|
||||
break;
|
||||
case SCTP_AUTHINFO:
|
||||
@ -3628,7 +3636,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
|
||||
|
||||
static struct sctp_tcb *
|
||||
sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p,
|
||||
in_port_t port,
|
||||
uint16_t port,
|
||||
struct mbuf *control,
|
||||
struct sctp_nets **net_p,
|
||||
int *error)
|
||||
@ -3734,7 +3742,6 @@ sctp_add_cookie(struct mbuf *init, int init_offset,
|
||||
int sig_offset;
|
||||
uint16_t cookie_sz;
|
||||
|
||||
mret = NULL;
|
||||
mret = sctp_get_mbuf_for_msg((sizeof(struct sctp_state_cookie) +
|
||||
sizeof(struct sctp_paramhdr)), 0,
|
||||
M_NOWAIT, 1, MT_DATA);
|
||||
@ -3931,7 +3938,9 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
struct sctphdr *sctphdr;
|
||||
int packet_length;
|
||||
int ret;
|
||||
#if defined(INET) || defined(INET6)
|
||||
uint32_t vrf_id;
|
||||
#endif
|
||||
#if defined(INET) || defined(INET6)
|
||||
#if !defined(__Panda__)
|
||||
struct mbuf *o_pak;
|
||||
@ -3957,12 +3966,13 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
sctp_m_freem(m);
|
||||
return (EFAULT);
|
||||
}
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (stcb) {
|
||||
vrf_id = stcb->asoc.vrf_id;
|
||||
} else {
|
||||
vrf_id = inp->def_vrf_id;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* fill in the HMAC digest for any AUTH chunk in the packet */
|
||||
if ((auth != NULL) && (stcb != NULL)) {
|
||||
sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid);
|
||||
@ -4338,7 +4348,11 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
* This means especially, that it is not set at the
|
||||
* SCTP layer. So use the value from the IP layer.
|
||||
*/
|
||||
#if defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
|
||||
flowlabel = ntohl(inp->ip_inp.inp.inp_flow);
|
||||
#else
|
||||
flowlabel = ntohl(((struct in6pcb *)inp)->in6p_flowinfo);
|
||||
#endif
|
||||
}
|
||||
flowlabel &= 0x000fffff;
|
||||
len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr);
|
||||
@ -4418,7 +4432,11 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
* SCTP layer. So use the value from the IP layer.
|
||||
*/
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Panda__) || defined(__Windows__) || defined(__Userspace__)
|
||||
#if defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
|
||||
tos_value = (ntohl(inp->ip_inp.inp.inp_flow) >> 20) & 0xff;
|
||||
#else
|
||||
tos_value = (ntohl(((struct in6pcb *)inp)->in6p_flowinfo) >> 20) & 0xff;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
tos_value &= 0xfc;
|
||||
@ -4736,6 +4754,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
#else
|
||||
if (ro->ro_rt) {
|
||||
RTFREE(ro->ro_rt);
|
||||
ro->ro_rt = NULL;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@ -4805,8 +4824,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
sctphdr->dest_port = dest_port;
|
||||
sctphdr->v_tag = v_tag;
|
||||
sctphdr->checksum = 0;
|
||||
#if defined(SCTP_WITH_NO_CSUM)
|
||||
SCTP_STAT_INCR(sctps_sendnocrc);
|
||||
#else
|
||||
sctphdr->checksum = sctp_calculate_cksum(m, 0);
|
||||
SCTP_STAT_INCR(sctps_sendswcrc);
|
||||
#endif
|
||||
if (tos_value == 0) {
|
||||
tos_value = inp->ip_inp.inp.inp_ip_tos;
|
||||
}
|
||||
@ -4846,9 +4869,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
struct mbuf *m;
|
||||
struct sctp_nets *net;
|
||||
struct sctp_init_chunk *init;
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct sctp_supported_addr_param *sup_addr;
|
||||
#endif
|
||||
struct sctp_adaptation_layer_indication *ali;
|
||||
struct sctp_supported_chunk_types_param *pr_supported;
|
||||
struct sctp_paramhdr *ph;
|
||||
@ -5730,6 +5751,14 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
}
|
||||
SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
|
||||
|
||||
/*
|
||||
* We might not overwrite the identification[] completely and on
|
||||
* some platforms time_entered will contain some padding.
|
||||
* Therefore zero out the cookie to avoid putting
|
||||
* uninitialized memory on the wire.
|
||||
*/
|
||||
memset(&stc, 0, sizeof(struct sctp_state_cookie));
|
||||
|
||||
/* the time I built cookie */
|
||||
(void)SCTP_GETTIME_TIMEVAL(&stc.time_entered);
|
||||
|
||||
@ -5892,6 +5921,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
memcpy(&stc.laddress, &dstconn->sconn_addr, sizeof(void *));
|
||||
stc.laddr_type = SCTP_CONN_ADDRESS;
|
||||
/* scope_id is only for v6 */
|
||||
stc.scope_id = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -5987,11 +6017,19 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
#if defined(__Userspace__)
|
||||
case AF_CONN:
|
||||
sconn = (struct sockaddr_conn *)to;
|
||||
stc.address[0] = 0;
|
||||
stc.address[1] = 0;
|
||||
stc.address[2] = 0;
|
||||
stc.address[3] = 0;
|
||||
memcpy(&stc.address, &sconn->sconn_addr, sizeof(void *));
|
||||
stc.addr_type = SCTP_CONN_ADDRESS;
|
||||
stc.laddress[0] = 0;
|
||||
stc.laddress[1] = 0;
|
||||
stc.laddress[2] = 0;
|
||||
stc.laddress[3] = 0;
|
||||
memcpy(&stc.laddress, &sconn->sconn_addr, sizeof(void *));
|
||||
stc.scope_id = 0;
|
||||
stc.laddr_type = SCTP_CONN_ADDRESS;
|
||||
stc.scope_id = 0;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@ -6427,17 +6465,16 @@ sctp_get_frag_point(struct sctp_tcb *stcb,
|
||||
static void
|
||||
sctp_set_prsctp_policy(struct sctp_stream_queue_pending *sp)
|
||||
{
|
||||
sp->pr_sctp_on = 0;
|
||||
/*
|
||||
* We assume that the user wants PR_SCTP_TTL if the user
|
||||
* provides a positive lifetime but does not specify any
|
||||
* PR_SCTP policy. This is a BAD assumption and causes
|
||||
* problems at least with the U-Vancovers MPI folks. I will
|
||||
* change this to be no policy means NO PR-SCTP.
|
||||
* PR_SCTP policy.
|
||||
*/
|
||||
if (PR_SCTP_ENABLED(sp->sinfo_flags)) {
|
||||
sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags);
|
||||
sp->pr_sctp_on = 1;
|
||||
} else if (sp->timetolive > 0) {
|
||||
sp->sinfo_flags |= SCTP_PR_SCTP_TTL;
|
||||
sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@ -6774,7 +6811,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
|
||||
/* TSNH */
|
||||
return;
|
||||
}
|
||||
if ((ca->m) && ca->sndlen) {
|
||||
if (ca->sndlen > 0) {
|
||||
m = SCTP_M_COPYM(ca->m, 0, M_COPYALL, M_NOWAIT);
|
||||
if (m == NULL) {
|
||||
/* can't copy so we are done */
|
||||
@ -6803,35 +6840,39 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
|
||||
}
|
||||
if (ca->sndrcv.sinfo_flags & SCTP_ABORT) {
|
||||
/* Abort this assoc with m as the user defined reason */
|
||||
if (m) {
|
||||
if (m != NULL) {
|
||||
SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), M_NOWAIT);
|
||||
} else {
|
||||
m = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
|
||||
0, M_NOWAIT, 1, MT_DATA);
|
||||
SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr);
|
||||
}
|
||||
if (m != NULL) {
|
||||
struct sctp_paramhdr *ph;
|
||||
|
||||
SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), M_NOWAIT);
|
||||
if (m) {
|
||||
ph = mtod(m, struct sctp_paramhdr *);
|
||||
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
|
||||
ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen);
|
||||
}
|
||||
/* We add one here to keep the assoc from
|
||||
* dis-appearing on us.
|
||||
*/
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED);
|
||||
/* sctp_abort_an_association calls sctp_free_asoc()
|
||||
* free association will NOT free it since we
|
||||
* incremented the refcnt .. we do this to prevent
|
||||
* it being freed and things getting tricky since
|
||||
* we could end up (from free_asoc) calling inpcb_free
|
||||
* which would get a recursive lock call to the
|
||||
* iterator lock.. But as a consequence of that the
|
||||
* stcb will return to us un-locked.. since free_asoc
|
||||
* returns with either no TCB or the TCB unlocked, we
|
||||
* must relock.. to unlock in the iterator timer :-0
|
||||
*/
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_add_int(&stcb->asoc.refcnt, -1);
|
||||
goto no_chunk_output;
|
||||
ph = mtod(m, struct sctp_paramhdr *);
|
||||
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
|
||||
ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen);
|
||||
}
|
||||
/* We add one here to keep the assoc from
|
||||
* dis-appearing on us.
|
||||
*/
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED);
|
||||
/* sctp_abort_an_association calls sctp_free_asoc()
|
||||
* free association will NOT free it since we
|
||||
* incremented the refcnt .. we do this to prevent
|
||||
* it being freed and things getting tricky since
|
||||
* we could end up (from free_asoc) calling inpcb_free
|
||||
* which would get a recursive lock call to the
|
||||
* iterator lock.. But as a consequence of that the
|
||||
* stcb will return to us un-locked.. since free_asoc
|
||||
* returns with either no TCB or the TCB unlocked, we
|
||||
* must relock.. to unlock in the iterator timer :-0
|
||||
*/
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_add_int(&stcb->asoc.refcnt, -1);
|
||||
goto no_chunk_output;
|
||||
} else {
|
||||
if (m) {
|
||||
ret = sctp_msg_append(stcb, net, m,
|
||||
@ -6914,8 +6955,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
|
||||
|
||||
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
|
||||
(stcb->asoc.total_flight > 0) &&
|
||||
(un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))
|
||||
) {
|
||||
(un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))) {
|
||||
do_chunk_output = 0;
|
||||
}
|
||||
if (do_chunk_output)
|
||||
@ -7057,13 +7097,10 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
|
||||
/* Gather the length of the send */
|
||||
struct mbuf *mat;
|
||||
|
||||
mat = m;
|
||||
ca->sndlen = 0;
|
||||
while (m) {
|
||||
ca->sndlen += SCTP_BUF_LEN(m);
|
||||
m = SCTP_BUF_NEXT(m);
|
||||
for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
|
||||
ca->sndlen += SCTP_BUF_LEN(mat);
|
||||
}
|
||||
ca->m = mat;
|
||||
}
|
||||
ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL,
|
||||
SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES,
|
||||
@ -7265,8 +7302,8 @@ sctp_clean_up_ctl(struct sctp_tcb *stcb, struct sctp_association *asoc, int so_l
|
||||
|
||||
static int
|
||||
sctp_can_we_split_this(struct sctp_tcb *stcb,
|
||||
uint32_t length,
|
||||
uint32_t goal_mtu, uint32_t frag_point, int eeor_on)
|
||||
uint32_t length,
|
||||
uint32_t goal_mtu, uint32_t frag_point, int eeor_on)
|
||||
{
|
||||
/* Make a decision on if I should split a
|
||||
* msg into multiple parts. This is only asked of
|
||||
@ -7325,18 +7362,18 @@ sctp_can_we_split_this(struct sctp_tcb *stcb,
|
||||
|
||||
static uint32_t
|
||||
sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
struct sctp_stream_out *strq,
|
||||
uint32_t goal_mtu,
|
||||
uint32_t frag_point,
|
||||
int *locked,
|
||||
int *giveup,
|
||||
int eeor_mode,
|
||||
int *bail,
|
||||
int so_locked
|
||||
struct sctp_stream_out *strq,
|
||||
uint32_t goal_mtu,
|
||||
uint32_t frag_point,
|
||||
int *locked,
|
||||
int *giveup,
|
||||
int eeor_mode,
|
||||
int *bail,
|
||||
int so_locked
|
||||
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
|
||||
SCTP_UNUSED
|
||||
SCTP_UNUSED
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
/* Move from the stream to the send_queue keeping track of the total */
|
||||
struct sctp_association *asoc;
|
||||
@ -7350,7 +7387,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
|
||||
SCTP_TCB_LOCK_ASSERT(stcb);
|
||||
asoc = &stcb->asoc;
|
||||
one_more_time:
|
||||
one_more_time:
|
||||
/*sa_ignore FREED_MEMORY*/
|
||||
sp = TAILQ_FIRST(&strq->outqueue);
|
||||
if (sp == NULL) {
|
||||
@ -7385,11 +7422,11 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
if ((sp->put_last_out == 0) && (sp->discard_rest == 0)) {
|
||||
SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n");
|
||||
SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d send_lock:%d\n",
|
||||
sp->sender_all_done,
|
||||
sp->length,
|
||||
sp->msg_is_complete,
|
||||
sp->put_last_out,
|
||||
send_lock_up);
|
||||
sp->sender_all_done,
|
||||
sp->length,
|
||||
sp->msg_is_complete,
|
||||
sp->put_last_out,
|
||||
send_lock_up);
|
||||
}
|
||||
if ((TAILQ_NEXT(sp, next) == NULL) && (send_lock_up == 0)) {
|
||||
SCTP_TCB_SEND_LOCK(stcb);
|
||||
@ -7462,7 +7499,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
|
||||
sp->msg_is_complete = 1;
|
||||
}
|
||||
re_look:
|
||||
re_look:
|
||||
length = sp->length;
|
||||
if (sp->msg_is_complete) {
|
||||
/* The message is complete */
|
||||
@ -7561,7 +7598,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
sp->data = sp->tail_mbuf = NULL;
|
||||
} else {
|
||||
struct mbuf *m;
|
||||
dont_do_it:
|
||||
dont_do_it:
|
||||
chk->data = SCTP_M_COPYM(sp->data, 0, to_move, M_NOWAIT);
|
||||
chk->last_mbuf = NULL;
|
||||
if (chk->data == NULL) {
|
||||
@ -7779,13 +7816,8 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
}
|
||||
chk->send_size += pads;
|
||||
}
|
||||
/* We only re-set the policy if it is on */
|
||||
if (sp->pr_sctp_on) {
|
||||
sctp_set_prsctp_policy(sp);
|
||||
if (PR_SCTP_ENABLED(chk->flags)) {
|
||||
asoc->pr_sctp_cnt++;
|
||||
chk->pr_sctp_on = 1;
|
||||
} else {
|
||||
chk->pr_sctp_on = 0;
|
||||
}
|
||||
if (sp->msg_is_complete && (sp->length == 0) && (sp->sender_all_done)) {
|
||||
/* All done pull and kill the message */
|
||||
@ -7826,7 +7858,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
strq->chunks_on_queues++;
|
||||
TAILQ_INSERT_TAIL(&asoc->send_queue, chk, sctp_next);
|
||||
asoc->send_queue_cnt++;
|
||||
out_of:
|
||||
out_of:
|
||||
if (send_lock_up) {
|
||||
SCTP_TCB_SEND_UNLOCK(stcb);
|
||||
}
|
||||
@ -7980,7 +8012,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/*
|
||||
/**
|
||||
* Ok this is the generic chunk service queue. we must do the
|
||||
* following: - Service the stream queue that is next, moving any
|
||||
* message (note I must get a complete message i.e. FIRST/MIDDLE and
|
||||
@ -9331,7 +9363,6 @@ sctp_send_cookie_ack(struct sctp_tcb *stcb)
|
||||
struct sctp_chunkhdr *hdr;
|
||||
struct sctp_tmit_chunk *chk;
|
||||
|
||||
cookie_ack = NULL;
|
||||
SCTP_TCB_LOCK_ASSERT(stcb);
|
||||
|
||||
cookie_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_chunkhdr), 0, M_NOWAIT, 1, MT_HEADER);
|
||||
@ -11083,6 +11114,7 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
|
||||
struct sctp_abort_chunk *abort;
|
||||
struct sctp_auth_chunk *auth = NULL;
|
||||
struct sctp_nets *net;
|
||||
uint32_t vtag;
|
||||
uint32_t auth_offset = 0;
|
||||
uint16_t cause_len, chunk_len, padding_len;
|
||||
|
||||
@ -11145,7 +11177,14 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
|
||||
/* Fill in the ABORT chunk header. */
|
||||
abort = mtod(m_abort, struct sctp_abort_chunk *);
|
||||
abort->ch.chunk_type = SCTP_ABORT_ASSOCIATION;
|
||||
abort->ch.chunk_flags = 0;
|
||||
if (stcb->asoc.peer_vtag == 0) {
|
||||
/* This happens iff the assoc is in COOKIE-WAIT state. */
|
||||
vtag = stcb->asoc.my_vtag;
|
||||
abort->ch.chunk_flags = SCTP_HAD_NO_TCB;
|
||||
} else {
|
||||
vtag = stcb->asoc.peer_vtag;
|
||||
abort->ch.chunk_flags = 0;
|
||||
}
|
||||
abort->ch.chunk_length = htons(chunk_len);
|
||||
/* Add padding, if necessary. */
|
||||
if (padding_len > 0) {
|
||||
@ -11157,7 +11196,7 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
|
||||
(void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net,
|
||||
(struct sockaddr *)&net->ro._l_addr,
|
||||
m_out, auth_offset, auth, stcb->asoc.authinfo.active_keyid, 1, 0, 0,
|
||||
stcb->sctp_ep->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag),
|
||||
stcb->sctp_ep->sctp_lport, stcb->rport, htonl(vtag),
|
||||
stcb->asoc.primary_destination->port, NULL,
|
||||
#if defined(__FreeBSD__)
|
||||
0, 0,
|
||||
@ -11232,7 +11271,10 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
|
||||
struct sctphdr *shout;
|
||||
struct sctp_chunkhdr *ch;
|
||||
struct udphdr *udp;
|
||||
int len, cause_len, padding_len, ret;
|
||||
int len, cause_len, padding_len;
|
||||
#if defined(INET) || defined(INET6)
|
||||
int ret;
|
||||
#endif
|
||||
#ifdef INET
|
||||
#if defined(__APPLE__) || defined(__Panda__)
|
||||
sctp_route_t ro;
|
||||
@ -11508,6 +11550,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
|
||||
/* Free the route if we got one back */
|
||||
if (ro.ro_rt) {
|
||||
RTFREE(ro.ro_rt);
|
||||
ro.ro_rt = NULL;
|
||||
}
|
||||
#else
|
||||
SCTP_IP_OUTPUT(ret, o_pak, NULL, NULL, vrf_id);
|
||||
@ -11564,8 +11607,12 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
|
||||
struct sockaddr_conn *sconn;
|
||||
|
||||
sconn = (struct sockaddr_conn *)src;
|
||||
#if defined(SCTP_WITH_NO_CSUM)
|
||||
SCTP_STAT_INCR(sctps_sendnocrc);
|
||||
#else
|
||||
shout->checksum = sctp_calculate_cksum(mout, 0);
|
||||
SCTP_STAT_INCR(sctps_sendswcrc);
|
||||
#endif
|
||||
#ifdef SCTP_PACKET_LOGGING
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
|
||||
sctp_packet_log(mout);
|
||||
@ -11574,7 +11621,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
|
||||
/* Don't alloc/free for each packet */
|
||||
if ((buffer = malloc(len)) != NULL) {
|
||||
m_copydata(mout, 0, len, buffer);
|
||||
ret = SCTP_BASE_VAR(conn_output)(sconn->sconn_addr, buffer, len, 0, 0);
|
||||
SCTP_BASE_VAR(conn_output)(sconn->sconn_addr, buffer, len, 0, 0);
|
||||
free(buffer);
|
||||
}
|
||||
sctp_m_freem(mout);
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 246687 2013-02-11 21:02:49Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 258765 2013-11-30 12:51:19Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -68,14 +68,6 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 246687 2013-02-11 21:02:49Z tuex
|
||||
#include <sys/unistd.h>
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
#if !defined(__Userspace_os_Windows)
|
||||
#if defined(ANDROID)
|
||||
#include <unistd.h>
|
||||
#include <ifaddrs-android-ext.h>
|
||||
#else
|
||||
#include <sys/unistd.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <user_socketvar.h>
|
||||
#endif
|
||||
|
||||
@ -90,8 +82,10 @@ struct sctp_base_info system_base_info;
|
||||
#endif
|
||||
|
||||
#if defined(__Userspace__)
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct ifaddrs *g_interfaces;
|
||||
#endif
|
||||
#endif
|
||||
/* FIX: we don't handle multiple link local scopes */
|
||||
/* "scopeless" replacement IN6_ARE_ADDR_EQUAL */
|
||||
#ifdef INET6
|
||||
@ -926,8 +920,13 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
|
||||
static int
|
||||
sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
|
||||
{
|
||||
int loopback_scope, ipv4_local_scope, local_scope, site_scope;
|
||||
int ipv4_addr_legal, ipv6_addr_legal;
|
||||
int loopback_scope;
|
||||
#if defined(INET)
|
||||
int ipv4_local_scope, ipv4_addr_legal;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
int local_scope, site_scope, ipv6_addr_legal;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
int conn_addr_legal;
|
||||
#endif
|
||||
@ -936,11 +935,15 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
|
||||
struct sctp_ifa *sctp_ifa;
|
||||
|
||||
loopback_scope = stcb->asoc.scope.loopback_scope;
|
||||
#if defined(INET)
|
||||
ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
|
||||
ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
local_scope = stcb->asoc.scope.local_scope;
|
||||
site_scope = stcb->asoc.scope.site_scope;
|
||||
ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
|
||||
ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
|
||||
#endif
|
||||
@ -968,7 +971,9 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sctp_ifa->address.sa.sa_family != to->sa_family) {
|
||||
continue;
|
||||
}
|
||||
switch (sctp_ifa->address.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
@ -2318,8 +2323,11 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
|
||||
struct sockaddr *dst)
|
||||
{
|
||||
struct sctp_paramhdr *phdr, parm_buf;
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct sctp_tcb *stcb;
|
||||
uint32_t ptype, plen;
|
||||
uint16_t ptype;
|
||||
#endif
|
||||
uint16_t plen;
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin4;
|
||||
#endif
|
||||
@ -2344,13 +2352,14 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
|
||||
sin6.sin6_port = sh->src_port;
|
||||
#endif
|
||||
|
||||
stcb = NULL;
|
||||
offset += sizeof(struct sctp_init_chunk);
|
||||
|
||||
phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
|
||||
while (phdr != NULL) {
|
||||
/* now we must see if we want the parameter */
|
||||
#if defined(INET) || defined(INET6)
|
||||
ptype = ntohs(phdr->param_type);
|
||||
#endif
|
||||
plen = ntohs(phdr->param_length);
|
||||
if (plen == 0) {
|
||||
break;
|
||||
@ -2534,7 +2543,7 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
|
||||
if (sh->v_tag) {
|
||||
/* we only go down this path if vtag is non-zero */
|
||||
stcb = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag),
|
||||
inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0);
|
||||
inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0);
|
||||
if (stcb) {
|
||||
return (stcb);
|
||||
}
|
||||
@ -2550,11 +2559,11 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
|
||||
}
|
||||
if (inp_p) {
|
||||
stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp,
|
||||
find_tcp_pool, vrf_id);
|
||||
find_tcp_pool, vrf_id);
|
||||
inp = *inp_p;
|
||||
} else {
|
||||
stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp,
|
||||
find_tcp_pool, vrf_id);
|
||||
find_tcp_pool, vrf_id);
|
||||
}
|
||||
SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp);
|
||||
if (stcb == NULL && inp) {
|
||||
@ -2740,8 +2749,13 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
inp->ip_inp.inp.inp_socket = so;
|
||||
#ifdef INET6
|
||||
#if !defined(__Userspace__) && !defined(__Windows__)
|
||||
if (MODULE_GLOBAL(ip6_auto_flowlabel)) {
|
||||
inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL;
|
||||
if (INP_SOCKAF(so) == AF_INET6) {
|
||||
if (MODULE_GLOBAL(ip6_auto_flowlabel)) {
|
||||
inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL;
|
||||
}
|
||||
if (MODULE_GLOBAL(ip6_v6only)) {
|
||||
inp->ip_inp.inp.inp_flags |= IN6P_IPV6_V6ONLY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -2863,7 +2877,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD)
|
||||
inp->ip_inp.inp.inpcb_mtx = lck_mtx_alloc_init(SCTP_BASE_INFO(mtx_grp), SCTP_BASE_INFO(mtx_attr));
|
||||
inp->ip_inp.inp.inpcb_mtx = lck_mtx_alloc_init(SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr);
|
||||
if (inp->ip_inp.inp.inpcb_mtx == NULL) {
|
||||
SCTP_PRINTF("in_pcballoc: can't alloc mutex! so=%p\n", (void *)so);
|
||||
#ifdef SCTP_MVRF
|
||||
@ -2872,12 +2886,14 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark);
|
||||
so->so_pcb = NULL;
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
|
||||
SCTP_UNLOCK_EXC(SCTP_BASE_INFO(ipi_ep_mtx));
|
||||
SCTP_UNLOCK_EXC(SCTP_BASE_INFO(sctbinfo).ipi_lock);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM);
|
||||
return (ENOMEM);
|
||||
}
|
||||
#elif defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
|
||||
lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr);
|
||||
#else
|
||||
lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(mtx_grp), SCTP_BASE_INFO(mtx_attr));
|
||||
lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).ipi_lock_grp, SCTP_BASE_INFO(sctbinfo).ipi_lock_attr);
|
||||
#endif
|
||||
#endif
|
||||
SCTP_INP_INFO_WLOCK();
|
||||
@ -2893,7 +2909,12 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
/* add it to the info area */
|
||||
LIST_INSERT_HEAD(&SCTP_BASE_INFO(listhead), inp, sctp_list);
|
||||
#if defined(__APPLE__)
|
||||
LIST_INSERT_HEAD(&SCTP_BASE_INFO(inplisthead), &inp->ip_inp.inp, inp_list);
|
||||
inp->ip_inp.inp.inp_pcbinfo = &SCTP_BASE_INFO(sctbinfo);
|
||||
#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
|
||||
LIST_INSERT_HEAD(SCTP_BASE_INFO(sctbinfo).listhead, &inp->ip_inp.inp, inp_list);
|
||||
#else
|
||||
LIST_INSERT_HEAD(SCTP_BASE_INFO(sctbinfo).ipi_listhead, &inp->ip_inp.inp, inp_list);
|
||||
#endif
|
||||
#endif
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
|
||||
@ -2927,9 +2948,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
m->initial_rto = SCTP_BASE_SYSCTL(sctp_rto_initial_default);
|
||||
m->initial_init_rto_max = SCTP_BASE_SYSCTL(sctp_init_rto_max_default);
|
||||
m->sctp_sack_freq = SCTP_BASE_SYSCTL(sctp_sack_freq_default);
|
||||
|
||||
m->max_open_streams_intome = MAX_SCTP_STREAMS;
|
||||
|
||||
m->max_init_times = SCTP_BASE_SYSCTL(sctp_init_rtx_max_default);
|
||||
m->max_send_times = SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default);
|
||||
m->def_net_failure = SCTP_BASE_SYSCTL(sctp_path_rtx_max_default);
|
||||
@ -2941,6 +2959,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
|
||||
m->sctp_default_cc_module = SCTP_BASE_SYSCTL(sctp_default_cc_module);
|
||||
m->sctp_default_ss_module = SCTP_BASE_SYSCTL(sctp_default_ss_module);
|
||||
m->max_open_streams_intome = SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default);
|
||||
/* number of streams to pre-open on a association */
|
||||
m->pre_open_stream_count = SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default);
|
||||
|
||||
@ -3139,7 +3158,9 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
|
||||
/* bind a ep to a socket address */
|
||||
struct sctppcbhead *head;
|
||||
struct sctp_inpcb *inp, *inp_tmp;
|
||||
#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
struct inpcb *ip_inp;
|
||||
#endif
|
||||
int port_reuse_active = 0;
|
||||
int bindall;
|
||||
#ifdef SCTP_MVRF
|
||||
@ -3153,7 +3174,9 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
|
||||
error = 0;
|
||||
bindall = 1;
|
||||
inp = (struct sctp_inpcb *)so->so_pcb;
|
||||
#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
ip_inp = (struct inpcb *)so->so_pcb;
|
||||
#endif
|
||||
#ifdef SCTP_DEBUG
|
||||
if (addr) {
|
||||
SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port: %d\n",
|
||||
@ -4382,7 +4405,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
#endif
|
||||
if (set_scope) {
|
||||
#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE
|
||||
stcb->ipv4_local_scope = 1;
|
||||
stcb->asoc.scope.ipv4_local_scope = 1;
|
||||
#else
|
||||
if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
|
||||
stcb->asoc.scope.ipv4_local_scope = 1;
|
||||
@ -4588,6 +4611,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
#endif
|
||||
SCTP_RTALLOC((sctp_route_t *)&net->ro, stcb->asoc.vrf_id);
|
||||
|
||||
#if !defined(__Userspace__)
|
||||
if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) {
|
||||
/* Get source address */
|
||||
net->ro._s_addr = sctp_source_address_selection(stcb->sctp_ep,
|
||||
@ -4617,6 +4641,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (net->mtu == 0) {
|
||||
switch (newaddr->sa_family) {
|
||||
#ifdef INET
|
||||
@ -5056,6 +5081,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
|
||||
asoc->nr_mapping_array = NULL;
|
||||
}
|
||||
SCTP_DECR_ASOC_COUNT();
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_TCB_LOCK_DESTROY(stcb);
|
||||
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
|
||||
LIST_REMOVE(stcb, sctp_tcbasocidhash);
|
||||
@ -5191,23 +5217,21 @@ sctp_delete_from_timewait(uint32_t tag, uint16_t lport, uint16_t rport)
|
||||
int i;
|
||||
|
||||
chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)];
|
||||
if (!LIST_EMPTY(chain)) {
|
||||
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
|
||||
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
|
||||
if ((twait_block->vtag_block[i].v_tag == tag) &&
|
||||
(twait_block->vtag_block[i].lport == lport) &&
|
||||
(twait_block->vtag_block[i].rport == rport)) {
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = 0;
|
||||
twait_block->vtag_block[i].v_tag = 0;
|
||||
twait_block->vtag_block[i].lport = 0;
|
||||
twait_block->vtag_block[i].rport = 0;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
|
||||
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
|
||||
if ((twait_block->vtag_block[i].v_tag == tag) &&
|
||||
(twait_block->vtag_block[i].lport == lport) &&
|
||||
(twait_block->vtag_block[i].rport == rport)) {
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = 0;
|
||||
twait_block->vtag_block[i].v_tag = 0;
|
||||
twait_block->vtag_block[i].lport = 0;
|
||||
twait_block->vtag_block[i].rport = 0;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5221,19 +5245,17 @@ sctp_is_in_timewait(uint32_t tag, uint16_t lport, uint16_t rport)
|
||||
|
||||
SCTP_INP_INFO_WLOCK();
|
||||
chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)];
|
||||
if (!LIST_EMPTY(chain)) {
|
||||
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
|
||||
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
|
||||
if ((twait_block->vtag_block[i].v_tag == tag) &&
|
||||
(twait_block->vtag_block[i].lport == lport) &&
|
||||
(twait_block->vtag_block[i].rport == rport)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
|
||||
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
|
||||
if ((twait_block->vtag_block[i].v_tag == tag) &&
|
||||
(twait_block->vtag_block[i].lport == lport) &&
|
||||
(twait_block->vtag_block[i].rport == rport)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
return (found);
|
||||
@ -5255,42 +5277,40 @@ sctp_add_vtag_to_timewait(uint32_t tag, uint32_t time, uint16_t lport, uint16_t
|
||||
(void)SCTP_GETTIME_TIMEVAL(&now);
|
||||
chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)];
|
||||
set = 0;
|
||||
if (!LIST_EMPTY(chain)) {
|
||||
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
|
||||
/* Block(s) present, lets find space, and expire on the fly */
|
||||
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
|
||||
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
|
||||
if ((twait_block->vtag_block[i].v_tag == 0) &&
|
||||
!set) {
|
||||
twait_block->vtag_block[i].tv_sec_at_expire =
|
||||
now.tv_sec + time;
|
||||
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
|
||||
if ((twait_block->vtag_block[i].v_tag == 0) &&
|
||||
!set) {
|
||||
twait_block->vtag_block[i].tv_sec_at_expire =
|
||||
now.tv_sec + time;
|
||||
twait_block->vtag_block[i].v_tag = tag;
|
||||
twait_block->vtag_block[i].lport = lport;
|
||||
twait_block->vtag_block[i].rport = rport;
|
||||
set = 1;
|
||||
} else if ((twait_block->vtag_block[i].v_tag) &&
|
||||
((long)twait_block->vtag_block[i].tv_sec_at_expire < now.tv_sec)) {
|
||||
/* Audit expires this guy */
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = 0;
|
||||
twait_block->vtag_block[i].v_tag = 0;
|
||||
twait_block->vtag_block[i].lport = 0;
|
||||
twait_block->vtag_block[i].rport = 0;
|
||||
if (set == 0) {
|
||||
/* Reuse it for my new tag */
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time;
|
||||
twait_block->vtag_block[i].v_tag = tag;
|
||||
twait_block->vtag_block[i].lport = lport;
|
||||
twait_block->vtag_block[i].rport = rport;
|
||||
set = 1;
|
||||
} else if ((twait_block->vtag_block[i].v_tag) &&
|
||||
((long)twait_block->vtag_block[i].tv_sec_at_expire < now.tv_sec)) {
|
||||
/* Audit expires this guy */
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = 0;
|
||||
twait_block->vtag_block[i].v_tag = 0;
|
||||
twait_block->vtag_block[i].lport = 0;
|
||||
twait_block->vtag_block[i].rport = 0;
|
||||
if (set == 0) {
|
||||
/* Reuse it for my new tag */
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time;
|
||||
twait_block->vtag_block[i].v_tag = tag;
|
||||
twait_block->vtag_block[i].lport = lport;
|
||||
twait_block->vtag_block[i].rport = rport;
|
||||
set = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (set) {
|
||||
/*
|
||||
* We only do up to the block where we can
|
||||
* place our tag for audits
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (set) {
|
||||
/*
|
||||
* We only do up to the block where we can
|
||||
* place our tag for audits
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Need to add a new block to chain */
|
||||
@ -5876,6 +5896,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
/* Insert new items here :> */
|
||||
|
||||
/* Get rid of LOCK */
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_TCB_LOCK_DESTROY(stcb);
|
||||
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
|
||||
if (from_inpcbfree == SCTP_NORMAL_PROC) {
|
||||
@ -6601,6 +6622,25 @@ sctp_pcb_init()
|
||||
LIST_INIT(&SCTP_BASE_INFO(listhead));
|
||||
#if defined(__APPLE__)
|
||||
LIST_INIT(&SCTP_BASE_INFO(inplisthead));
|
||||
#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
|
||||
SCTP_BASE_INFO(sctbinfo).listhead = &SCTP_BASE_INFO(inplisthead);
|
||||
SCTP_BASE_INFO(sctbinfo).mtx_grp_attr = lck_grp_attr_alloc_init();
|
||||
lck_grp_attr_setdefault(SCTP_BASE_INFO(sctbinfo).mtx_grp_attr);
|
||||
SCTP_BASE_INFO(sctbinfo).mtx_grp = lck_grp_alloc_init("sctppcb", SCTP_BASE_INFO(sctbinfo).mtx_grp_attr);
|
||||
SCTP_BASE_INFO(sctbinfo).mtx_attr = lck_attr_alloc_init();
|
||||
lck_attr_setdefault(SCTP_BASE_INFO(sctbinfo).mtx_attr);
|
||||
#else
|
||||
SCTP_BASE_INFO(sctbinfo).ipi_listhead = &SCTP_BASE_INFO(inplisthead);
|
||||
SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr = lck_grp_attr_alloc_init();
|
||||
lck_grp_attr_setdefault(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr);
|
||||
SCTP_BASE_INFO(sctbinfo).ipi_lock_grp = lck_grp_alloc_init("sctppcb", SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr);
|
||||
SCTP_BASE_INFO(sctbinfo).ipi_lock_attr = lck_attr_alloc_init();
|
||||
lck_attr_setdefault(SCTP_BASE_INFO(sctbinfo).ipi_lock_attr);
|
||||
#endif
|
||||
#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)
|
||||
SCTP_BASE_INFO(sctbinfo).ipi_gc = sctp_gc;
|
||||
in_pcbinfo_attach(&SCTP_BASE_INFO(sctbinfo));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -6674,17 +6714,6 @@ sctp_pcb_init()
|
||||
|
||||
|
||||
/* Master Lock INIT for info structure */
|
||||
#if defined(__APPLE__)
|
||||
/* allocate the lock group attribute for SCTP PCB mutexes */
|
||||
SCTP_BASE_INFO(mtx_grp_attr) = lck_grp_attr_alloc_init();
|
||||
lck_grp_attr_setdefault(SCTP_BASE_INFO(mtx_grp_attr));
|
||||
/* allocate the lock group for SCTP PCB mutexes */
|
||||
SCTP_BASE_INFO(mtx_grp) = lck_grp_alloc_init("sctppcb",
|
||||
SCTP_BASE_INFO(mtx_grp_attr));
|
||||
/* allocate the lock attribute for SCTP PCB mutexes */
|
||||
SCTP_BASE_INFO(mtx_attr) = lck_attr_alloc_init();
|
||||
lck_attr_setdefault(SCTP_BASE_INFO(mtx_attr));
|
||||
#endif /* __APPLE__ */
|
||||
SCTP_INP_INFO_LOCK_INIT();
|
||||
SCTP_STATLOG_INIT_LOCK();
|
||||
|
||||
@ -6722,7 +6751,6 @@ sctp_pcb_init()
|
||||
for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) {
|
||||
LIST_INIT(&SCTP_BASE_INFO(vtag_timewait)[i]);
|
||||
}
|
||||
|
||||
#if defined(SCTP_PROCESS_LEVEL_LOCKS)
|
||||
#if defined(__Userspace_os_Windows)
|
||||
InitializeConditionVariable(&sctp_it_ctl.iterator_wakeup);
|
||||
@ -6777,37 +6805,9 @@ sctp_pcb_finish(void)
|
||||
struct sctp_tagblock *twait_block, *prev_twait_block;
|
||||
struct sctp_laddr *wi, *nwi;
|
||||
int i;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
/* Free BSD the it thread never exits
|
||||
* but we do clean up. The only way
|
||||
* freebsd reaches here if we have VRF's
|
||||
* but we still add the ifdef to make it
|
||||
* compile on old versions.
|
||||
*/
|
||||
{
|
||||
struct sctp_iterator *it, *nit;
|
||||
|
||||
SCTP_IPI_ITERATOR_WQ_LOCK();
|
||||
TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
|
||||
if (it->vn != curvnet) {
|
||||
continue;
|
||||
}
|
||||
TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
|
||||
if (it->function_atend != NULL) {
|
||||
(*it->function_atend) (it->pointer, it->val);
|
||||
}
|
||||
SCTP_FREE(it,SCTP_M_ITER);
|
||||
}
|
||||
SCTP_IPI_ITERATOR_WQ_UNLOCK();
|
||||
SCTP_ITERATOR_LOCK();
|
||||
if ((sctp_it_ctl.cur_it) &&
|
||||
(sctp_it_ctl.cur_it->vn == curvnet)) {
|
||||
sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT;
|
||||
}
|
||||
SCTP_ITERATOR_UNLOCK();
|
||||
}
|
||||
#else
|
||||
struct sctp_iterator *it, *nit;
|
||||
|
||||
#if !defined(__FreeBSD__)
|
||||
/* Notify the iterator to exit. */
|
||||
SCTP_IPI_ITERATOR_WQ_LOCK();
|
||||
sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_MUST_EXIT;
|
||||
@ -6815,6 +6815,9 @@ sctp_pcb_finish(void)
|
||||
SCTP_IPI_ITERATOR_WQ_UNLOCK();
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)
|
||||
in_pcbinfo_detach(&SCTP_BASE_INFO(sctbinfo));
|
||||
#endif
|
||||
SCTP_IPI_ITERATOR_WQ_LOCK();
|
||||
do {
|
||||
msleep(&sctp_it_ctl.iterator_flags,
|
||||
@ -6823,8 +6826,6 @@ sctp_pcb_finish(void)
|
||||
} while ((sctp_it_ctl.iterator_flags & SCTP_ITERATOR_EXITED) == 0);
|
||||
thread_deallocate(sctp_it_ctl.thread_proc);
|
||||
SCTP_IPI_ITERATOR_WQ_UNLOCK();
|
||||
SCTP_IPI_ITERATOR_WQ_DESTROY();
|
||||
SCTP_ITERATOR_LOCK_DESTROY();
|
||||
#endif
|
||||
#if defined(__Windows__)
|
||||
if (sctp_it_ctl.iterator_thread_obj != NULL) {
|
||||
@ -6839,7 +6840,56 @@ sctp_pcb_finish(void)
|
||||
ObDereferenceObject(sctp_it_ctl.iterator_thread_obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__Userspace__)
|
||||
if (sctp_it_ctl.thread_proc) {
|
||||
#if defined(__Userspace_os_Windows)
|
||||
WaitForSingleObject(sctp_it_ctl.thread_proc, INFINITE);
|
||||
CloseHandle(sctp_it_ctl.thread_proc);
|
||||
sctp_it_ctl.thread_proc = NULL;
|
||||
#else
|
||||
pthread_join(sctp_it_ctl.thread_proc, NULL);
|
||||
sctp_it_ctl.thread_proc = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(SCTP_PROCESS_LEVEL_LOCKS)
|
||||
#if defined(__Userspace_os_Windows)
|
||||
DeleteConditionVariable(&sctp_it_ctl.iterator_wakeup);
|
||||
#else
|
||||
pthread_cond_destroy(&sctp_it_ctl.iterator_wakeup);
|
||||
#endif
|
||||
#endif
|
||||
/* In FreeBSD the iterator thread never exits
|
||||
* but we do clean up.
|
||||
* The only way FreeBSD reaches here is if we have VRF's
|
||||
* but we still add the ifdef to make it compile on old versions.
|
||||
*/
|
||||
SCTP_IPI_ITERATOR_WQ_LOCK();
|
||||
TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
|
||||
if (it->vn != curvnet) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
|
||||
if (it->function_atend != NULL) {
|
||||
(*it->function_atend) (it->pointer, it->val);
|
||||
}
|
||||
SCTP_FREE(it,SCTP_M_ITER);
|
||||
}
|
||||
SCTP_IPI_ITERATOR_WQ_UNLOCK();
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
|
||||
SCTP_ITERATOR_LOCK();
|
||||
if ((sctp_it_ctl.cur_it) &&
|
||||
(sctp_it_ctl.cur_it->vn == curvnet)) {
|
||||
sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT;
|
||||
}
|
||||
SCTP_ITERATOR_UNLOCK();
|
||||
#endif
|
||||
#if !defined(__FreeBSD__)
|
||||
SCTP_IPI_ITERATOR_WQ_DESTROY();
|
||||
SCTP_ITERATOR_LOCK_DESTROY();
|
||||
#endif
|
||||
SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer));
|
||||
SCTP_WQ_ADDR_LOCK();
|
||||
LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
|
||||
@ -6877,7 +6927,9 @@ sctp_pcb_finish(void)
|
||||
SCTP_HASH_FREE(SCTP_BASE_INFO(vrf_ifn_hash), SCTP_BASE_INFO(vrf_ifn_hashmark));
|
||||
#if defined(__Userspace__) && !defined(__Userspace_os_Windows)
|
||||
/* free memory allocated by getifaddrs call */
|
||||
#if defined(INET) || defined(INET6)
|
||||
freeifaddrs(g_interfaces);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* free the TIMEWAIT list elements malloc'd in the function
|
||||
@ -6909,16 +6961,20 @@ sctp_pcb_finish(void)
|
||||
SCTP_IPI_COUNT_DESTROY();
|
||||
#endif
|
||||
SCTP_STATLOG_DESTROY();
|
||||
#if !defined(__Userspace__)
|
||||
SCTP_INP_INFO_LOCK_DESTROY();
|
||||
#endif
|
||||
|
||||
SCTP_WQ_ADDR_DESTROY();
|
||||
|
||||
#if defined(__APPLE__)
|
||||
lck_grp_attr_free(SCTP_BASE_INFO(mtx_grp_attr));
|
||||
lck_grp_free(SCTP_BASE_INFO(mtx_grp));
|
||||
lck_attr_free(SCTP_BASE_INFO(mtx_attr));
|
||||
#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
|
||||
lck_grp_attr_free(SCTP_BASE_INFO(sctbinfo).mtx_grp_attr);
|
||||
lck_grp_free(SCTP_BASE_INFO(sctbinfo).mtx_grp);
|
||||
lck_attr_free(SCTP_BASE_INFO(sctbinfo).mtx_attr);
|
||||
#else
|
||||
lck_grp_attr_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr);
|
||||
lck_grp_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp);
|
||||
lck_attr_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_attr);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
SCTP_TIMERQ_LOCK_DESTROY();
|
||||
@ -7656,30 +7712,28 @@ skip_vtag_check:
|
||||
|
||||
chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)];
|
||||
/* Now what about timed wait ? */
|
||||
if (!LIST_EMPTY(chain)) {
|
||||
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
|
||||
/*
|
||||
* Block(s) are present, lets see if we have this tag in the
|
||||
* list
|
||||
*/
|
||||
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
|
||||
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
|
||||
if (twait_block->vtag_block[i].v_tag == 0) {
|
||||
/* not used */
|
||||
continue;
|
||||
} else if ((long)twait_block->vtag_block[i].tv_sec_at_expire <
|
||||
now->tv_sec) {
|
||||
/* Audit expires this guy */
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = 0;
|
||||
twait_block->vtag_block[i].v_tag = 0;
|
||||
twait_block->vtag_block[i].lport = 0;
|
||||
twait_block->vtag_block[i].rport = 0;
|
||||
} else if ((twait_block->vtag_block[i].v_tag == tag) &&
|
||||
(twait_block->vtag_block[i].lport == lport) &&
|
||||
(twait_block->vtag_block[i].rport == rport)) {
|
||||
/* Bad tag, sorry :< */
|
||||
SCTP_INP_INFO_RUNLOCK();
|
||||
return (0);
|
||||
}
|
||||
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
|
||||
if (twait_block->vtag_block[i].v_tag == 0) {
|
||||
/* not used */
|
||||
continue;
|
||||
} else if ((long)twait_block->vtag_block[i].tv_sec_at_expire <
|
||||
now->tv_sec) {
|
||||
/* Audit expires this guy */
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = 0;
|
||||
twait_block->vtag_block[i].v_tag = 0;
|
||||
twait_block->vtag_block[i].lport = 0;
|
||||
twait_block->vtag_block[i].rport = 0;
|
||||
} else if ((twait_block->vtag_block[i].v_tag == tag) &&
|
||||
(twait_block->vtag_block[i].lport == lport) &&
|
||||
(twait_block->vtag_block[i].rport == rport)) {
|
||||
/* Bad tag, sorry :< */
|
||||
SCTP_INP_INFO_RUNLOCK();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 246687 2013-02-11 21:02:49Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 254248 2013-08-12 13:52:15Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_PCB_H_
|
||||
@ -189,6 +189,7 @@ struct sctp_epinfo {
|
||||
|
||||
#if defined(__APPLE__)
|
||||
struct inpcbhead inplisthead;
|
||||
struct inpcbinfo sctbinfo;
|
||||
#endif
|
||||
/* ep zone info */
|
||||
sctp_zone_t ipi_zone_ep;
|
||||
@ -223,20 +224,12 @@ struct sctp_epinfo {
|
||||
userland_mutex_t wq_addr_mtx;
|
||||
#elif defined(__APPLE__)
|
||||
#ifdef _KERN_LOCKS_H_
|
||||
lck_grp_attr_t *mtx_grp_attr;
|
||||
lck_grp_t *mtx_grp;
|
||||
lck_attr_t *mtx_attr;
|
||||
lck_rw_t *ipi_ep_mtx;
|
||||
lck_mtx_t *ipi_addr_mtx;
|
||||
lck_mtx_t *ipi_count_mtx;
|
||||
lck_mtx_t *ipi_pktlog_mtx;
|
||||
lck_mtx_t *logging_mtx;
|
||||
lck_mtx_t *wq_addr_mtx;
|
||||
#else
|
||||
void *mtx_grp_attr;
|
||||
void *mtx_grp;
|
||||
void *mtx_attr;
|
||||
void *ipi_ep_mtx;
|
||||
void *ipi_count_mtx;
|
||||
void *logging_mtx;
|
||||
#endif /* _KERN_LOCKS_H_ */
|
||||
@ -469,8 +462,8 @@ struct sctp_inpcb {
|
||||
|
||||
/* back pointer to our socket */
|
||||
struct socket *sctp_socket;
|
||||
uint64_t sctp_features; /* Feature flags */
|
||||
uint32_t sctp_flags; /* INP state flag set */
|
||||
uint32_t sctp_features; /* Feature flags */
|
||||
uint32_t sctp_mobility_features; /* Mobility Feature flags */
|
||||
struct sctp_pcb sctp_ep;/* SCTP ep data */
|
||||
/* head of the hash of all associations */
|
||||
|
@ -126,6 +126,8 @@
|
||||
|
||||
#define SCTP_INP_INFO_LOCK_INIT() \
|
||||
InitializeCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx))
|
||||
#define SCTP_INP_INFO_LOCK_DESTROY() \
|
||||
DeleteCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx))
|
||||
#define SCTP_INP_INFO_RLOCK() \
|
||||
EnterCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx))
|
||||
#define SCTP_INP_INFO_TRYLOCK() \
|
||||
@ -275,6 +277,8 @@
|
||||
|
||||
#define SCTP_INP_INFO_LOCK_INIT() \
|
||||
(void)pthread_mutex_init(&SCTP_BASE_INFO(ipi_ep_mtx), NULL)
|
||||
#define SCTP_INP_INFO_LOCK_DESTROY() \
|
||||
(void)pthread_mutex_destroy(&SCTP_BASE_INFO(ipi_ep_mtx))
|
||||
#define SCTP_INP_INFO_RLOCK() \
|
||||
(void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_ep_mtx))
|
||||
#define SCTP_INP_INFO_TRYLOCK() \
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*-
|
||||
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
|
||||
* Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
|
||||
* Copyright (c) 2008-2013, by Michael Tuexen. All rights reserved.
|
||||
* Copyright (c) 2013, by Lally Singh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@ -30,26 +31,84 @@
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_sha1.h>
|
||||
#if !defined(__Userspace_os_Windows)
|
||||
#include <sys/param.h>
|
||||
#if !defined(__Windows__)
|
||||
|
||||
#if defined(SCTP_USE_NSS_SHA1)
|
||||
/* A SHA-1 Digest is 160 bits, or 20 bytes */
|
||||
#define SHA_DIGEST_LENGTH (20)
|
||||
|
||||
void
|
||||
sctp_sha1_init(struct sctp_sha1_context *ctx)
|
||||
{
|
||||
ctx->pk11_ctx = PK11_CreateDigestContext(SEC_OID_SHA1);
|
||||
PK11_DigestBegin(ctx->pk11_ctx);
|
||||
}
|
||||
|
||||
void
|
||||
sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz)
|
||||
{
|
||||
PK11_DigestOp(ctx->pk11_ctx, ptr, siz);
|
||||
}
|
||||
|
||||
void
|
||||
sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx)
|
||||
{
|
||||
unsigned int output_len = 0;
|
||||
|
||||
PK11_DigestFinal(ctx->pk11_ctx, digest, &output_len, SHA_DIGEST_LENGTH);
|
||||
PK11_DestroyContext(ctx->pk11_ctx, PR_TRUE);
|
||||
}
|
||||
|
||||
#elif defined(SCTP_USE_OPENSSL_SHA1)
|
||||
|
||||
void
|
||||
sctp_sha1_init(struct sctp_sha1_context *ctx)
|
||||
{
|
||||
SHA1_Init(&ctx->sha_ctx);
|
||||
}
|
||||
|
||||
void
|
||||
sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz)
|
||||
{
|
||||
SHA1_Update(&ctx->sha_ctx, ptr, (unsigned long)siz);
|
||||
}
|
||||
|
||||
void
|
||||
sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx)
|
||||
{
|
||||
SHA1_Final(digest, &ctx->sha_ctx);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <string.h>
|
||||
#if defined(__Userspace_os_Windows)
|
||||
#include <winsock2.h>
|
||||
#elif !defined(__Windows__)
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#if !defined(__Userspace__)
|
||||
#include <sys/systm.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#define F1(B,C,D) (((B & C) | ((~B) & D))) /* 0 <= t <= 19 */
|
||||
#define F2(B,C,D) (B ^ C ^ D) /* 20 <= t <= 39 */
|
||||
#define F3(B,C,D) ((B & C) | (B & D) | (C & D)) /* 40 <= t <= 59 */
|
||||
#define F4(B,C,D) (B ^ C ^ D) /* 600 <= t <= 79 */
|
||||
|
||||
/* circular shift */
|
||||
#define CSHIFT(A,B) ((B << A) | (B >> (32-A)))
|
||||
|
||||
#define K1 0x5a827999 /* 0 <= t <= 19 */
|
||||
#define K2 0x6ed9eba1 /* 20 <= t <= 39 */
|
||||
#define K3 0x8f1bbcdc /* 40 <= t <= 59 */
|
||||
#define K4 0xca62c1d6 /* 60 <= t <= 79 */
|
||||
|
||||
#define H0INIT 0x67452301
|
||||
#define H1INIT 0xefcdab89
|
||||
#define H2INIT 0x98badcfe
|
||||
#define H3INIT 0x10325476
|
||||
#define H4INIT 0xc3d2e1f0
|
||||
|
||||
void
|
||||
SHA1_Init(struct sha1_context *ctx)
|
||||
sctp_sha1_init(struct sctp_sha1_context *ctx)
|
||||
{
|
||||
/* Init the SHA-1 context structure */
|
||||
ctx->A = 0;
|
||||
@ -69,7 +128,7 @@ SHA1_Init(struct sha1_context *ctx)
|
||||
}
|
||||
|
||||
static void
|
||||
sha1_process_a_block(struct sha1_context *ctx, unsigned int *block)
|
||||
sctp_sha1_process_a_block(struct sctp_sha1_context *ctx, unsigned int *block)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -133,11 +192,10 @@ sha1_process_a_block(struct sha1_context *ctx, unsigned int *block)
|
||||
ctx->H4 = (ctx->H4) + (ctx->E);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SHA1_Update(struct sha1_context *ctx, const unsigned char *ptr, int siz)
|
||||
sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz)
|
||||
{
|
||||
int number_left, left_to_fill;
|
||||
unsigned int number_left, left_to_fill;
|
||||
|
||||
number_left = siz;
|
||||
while (number_left > 0) {
|
||||
@ -154,7 +212,7 @@ SHA1_Update(struct sha1_context *ctx, const unsigned char *ptr, int siz)
|
||||
/* block is now full, process it */
|
||||
memcpy(&ctx->sha_block[ctx->how_many_in_block],
|
||||
ptr, left_to_fill);
|
||||
sha1_process_a_block(ctx,
|
||||
sctp_sha1_process_a_block(ctx,
|
||||
(unsigned int *)ctx->sha_block);
|
||||
number_left -= left_to_fill;
|
||||
ctx->running_total += left_to_fill;
|
||||
@ -165,7 +223,7 @@ SHA1_Update(struct sha1_context *ctx, const unsigned char *ptr, int siz)
|
||||
}
|
||||
|
||||
void
|
||||
SHA1_Final(unsigned char *digest, struct sha1_context *ctx)
|
||||
sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx)
|
||||
{
|
||||
/*
|
||||
* if any left in block fill with padding and process. Then transfer
|
||||
@ -191,7 +249,7 @@ SHA1_Final(unsigned char *digest, struct sha1_context *ctx)
|
||||
left_to_fill = sizeof(ctx->sha_block) - ctx->how_many_in_block;
|
||||
if (left_to_fill == 0) {
|
||||
/* Should not really happen but I am paranoid */
|
||||
sha1_process_a_block(ctx,
|
||||
sctp_sha1_process_a_block(ctx,
|
||||
(unsigned int *)ctx->sha_block);
|
||||
/* init last block, a bit different than the rest */
|
||||
ctx->sha_block[0] = '\x80';
|
||||
@ -200,7 +258,7 @@ SHA1_Final(unsigned char *digest, struct sha1_context *ctx)
|
||||
}
|
||||
} else if (left_to_fill == 1) {
|
||||
ctx->sha_block[ctx->how_many_in_block] = '\x80';
|
||||
sha1_process_a_block(ctx,
|
||||
sctp_sha1_process_a_block(ctx,
|
||||
(unsigned int *)ctx->sha_block);
|
||||
/* init last block */
|
||||
memset(ctx->sha_block, 0, sizeof(ctx->sha_block));
|
||||
@ -211,7 +269,7 @@ SHA1_Final(unsigned char *digest, struct sha1_context *ctx)
|
||||
i++) {
|
||||
ctx->sha_block[i] = 0x0;
|
||||
}
|
||||
sha1_process_a_block(ctx,
|
||||
sctp_sha1_process_a_block(ctx,
|
||||
(unsigned int *)ctx->sha_block);
|
||||
/* init last block */
|
||||
memset(ctx->sha_block, 0, sizeof(ctx->sha_block));
|
||||
@ -220,7 +278,7 @@ SHA1_Final(unsigned char *digest, struct sha1_context *ctx)
|
||||
ctx->running_total *= 8;
|
||||
ptr = (unsigned int *)&ctx->sha_block[60];
|
||||
*ptr = htonl(ctx->running_total);
|
||||
sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block);
|
||||
sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block);
|
||||
} else {
|
||||
/*
|
||||
* easy case, we just pad this message to size - end with 0
|
||||
@ -238,7 +296,7 @@ SHA1_Final(unsigned char *digest, struct sha1_context *ctx)
|
||||
ctx->running_total *= 8;
|
||||
ptr = (unsigned int *)&ctx->sha_block[60];
|
||||
*ptr = htonl(ctx->running_total);
|
||||
sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block);
|
||||
sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block);
|
||||
}
|
||||
/* transfer the digest back to the user */
|
||||
digest[3] = (ctx->H0 & 0xff);
|
||||
@ -266,3 +324,5 @@ SHA1_Final(unsigned char *digest, struct sha1_context *ctx)
|
||||
digest[17] = ((ctx->H4 >> 16) & 0xff);
|
||||
digest[16] = ((ctx->H4 >> 24) & 0xff);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -36,12 +36,31 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __SCTP_SLA1_h__
|
||||
#define __SCTP_SLA1_h__
|
||||
#ifndef __NETINET_SCTP_SHA1_H__
|
||||
#define __NETINET_SCTP_SHA1_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(SCTP_USE_NSS_SHA1)
|
||||
#if defined(__Userspace_os_Darwin)
|
||||
/* The NSS sources require __APPLE__ to be defined.
|
||||
* XXX: Remove this ugly hack once the platform defines have been cleaned up.
|
||||
*/
|
||||
#define __APPLE__
|
||||
#endif
|
||||
#include <pk11pub.h>
|
||||
#if defined(__Userspace_os_Darwin)
|
||||
#undef __APPLE__
|
||||
#endif
|
||||
#elif defined(SCTP_USE_OPENSSL_SHA1)
|
||||
#include <openssl/sha.h>
|
||||
#endif
|
||||
|
||||
struct sha1_context {
|
||||
struct sctp_sha1_context {
|
||||
#if defined(SCTP_USE_NSS_SHA1)
|
||||
struct PK11Context *pk11_ctx;
|
||||
#elif defined(SCTP_USE_OPENSSL_SHA1)
|
||||
SHA_CTX sha_ctx;
|
||||
#else
|
||||
unsigned int A;
|
||||
unsigned int B;
|
||||
unsigned int C;
|
||||
@ -59,28 +78,8 @@ struct sha1_context {
|
||||
/* collected so far */
|
||||
int how_many_in_block;
|
||||
unsigned int running_total;
|
||||
#endif
|
||||
};
|
||||
typedef struct sha1_context SHA1_CTX;
|
||||
|
||||
#define F1(B,C,D) (((B & C) | ((~B) & D))) /* 0 <= t <= 19 */
|
||||
#define F2(B,C,D) (B ^ C ^ D) /* 20 <= t <= 39 */
|
||||
#define F3(B,C,D) ((B & C) | (B & D) | (C & D)) /* 40 <= t <= 59 */
|
||||
#define F4(B,C,D) (B ^ C ^ D) /* 600 <= t <= 79 */
|
||||
|
||||
/* circular shift */
|
||||
#define CSHIFT(A,B) ((B << A) | (B >> (32-A)))
|
||||
|
||||
#define K1 0x5a827999 /* 0 <= t <= 19 */
|
||||
#define K2 0x6ed9eba1 /* 20 <= t <= 39 */
|
||||
#define K3 0x8f1bbcdc /* 40 <= t <= 59 */
|
||||
#define K4 0xca62c1d6 /* 60 <= t <= 79 */
|
||||
|
||||
#define H0INIT 0x67452301
|
||||
#define H1INIT 0xefcdab89
|
||||
#define H2INIT 0x98badcfe
|
||||
#define H3INIT 0x10325476
|
||||
#define H4INIT 0xc3d2e1f0
|
||||
|
||||
|
||||
#if (defined(__APPLE__) && defined(KERNEL))
|
||||
#ifndef _KERNEL
|
||||
@ -90,9 +89,9 @@ typedef struct sha1_context SHA1_CTX;
|
||||
|
||||
#if defined(_KERNEL) || defined(__Userspace__)
|
||||
|
||||
void SHA1_Init(struct sha1_context *);
|
||||
void SHA1_Update(struct sha1_context *, const unsigned char *, int);
|
||||
void SHA1_Final(unsigned char *, struct sha1_context *);
|
||||
void sctp_sha1_init(struct sctp_sha1_context *);
|
||||
void sctp_sha1_update(struct sctp_sha1_context *, const unsigned char *, unsigned int);
|
||||
void sctp_sha1_final(unsigned char *, struct sctp_sha1_context *);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 246595 2013-02-09 17:26:14Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 255190 2013-09-03 19:31:59Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_STRUCTS_H_
|
||||
@ -236,6 +236,9 @@ struct sctp_net_route {
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)
|
||||
struct ifaddr *ro_srcia;
|
||||
#endif
|
||||
#if !defined(APPLE_LEOPARD)
|
||||
uint32_t ro_flags;
|
||||
#endif
|
||||
@ -493,7 +496,6 @@ struct sctp_tmit_chunk {
|
||||
uint8_t do_rtt;
|
||||
uint8_t book_size_scale;
|
||||
uint8_t no_fr_allowed;
|
||||
uint8_t pr_sctp_on;
|
||||
uint8_t copy_by_ref;
|
||||
uint8_t window_probe;
|
||||
};
|
||||
@ -568,7 +570,6 @@ struct sctp_stream_queue_pending {
|
||||
uint8_t holds_key_ref;
|
||||
uint8_t msg_is_complete;
|
||||
uint8_t some_taken;
|
||||
uint8_t pr_sctp_on;
|
||||
uint8_t sender_all_done;
|
||||
uint8_t put_last_out;
|
||||
uint8_t discard_rest;
|
||||
@ -1252,7 +1253,7 @@ struct sctp_association {
|
||||
/* JRS 5/21/07 - CMT PF variable */
|
||||
uint8_t sctp_cmt_pf;
|
||||
uint8_t use_precise_time;
|
||||
uint32_t sctp_features;
|
||||
uint64_t sctp_features;
|
||||
uint16_t port; /* remote UDP encapsulation port */
|
||||
/*
|
||||
* The mapping array is used to track out of order sequences above
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 246595 2013-02-09 17:26:14Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 254672 2013-08-22 20:29:57Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -93,6 +93,7 @@ sctp_init_sysctls()
|
||||
SCTP_BASE_SYSCTL(sctp_path_rtx_max_default) = SCTPCTL_PATH_RTX_MAX_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_path_pf_threshold) = SCTPCTL_PATH_PF_THRESHOLD_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_add_more_threshold) = SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default) = SCTPCTL_INCOMING_STREAMS_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default) = SCTPCTL_OUTGOING_STREAMS_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT;
|
||||
/* EY */
|
||||
@ -491,7 +492,11 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
|
||||
xinpcb.last = 0;
|
||||
xinpcb.local_port = ntohs(inp->sctp_lport);
|
||||
xinpcb.flags = inp->sctp_flags;
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000048
|
||||
xinpcb.features = (uint32_t)inp->sctp_features;
|
||||
#else
|
||||
xinpcb.features = inp->sctp_features;
|
||||
#endif
|
||||
xinpcb.total_sends = inp->total_sends;
|
||||
xinpcb.total_recvs = inp->total_recvs;
|
||||
xinpcb.total_nospaces = inp->total_nospaces;
|
||||
@ -788,6 +793,7 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), SCTPCTL_PATH_RTX_MAX_MIN, SCTPCTL_PATH_RTX_MAX_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_path_pf_threshold), SCTPCTL_PATH_PF_THRESHOLD_MIN, SCTPCTL_PATH_PF_THRESHOLD_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTPCTL_ADD_MORE_ON_OUTPUT_MIN, SCTPCTL_ADD_MORE_ON_OUTPUT_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default), SCTPCTL_INCOMING_STREAMS_MIN, SCTPCTL_INCOMING_STREAMS_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), SCTPCTL_OUTGOING_STREAMS_MIN, SCTPCTL_OUTGOING_STREAMS_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_on_off), SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX);
|
||||
/* EY */
|
||||
@ -1180,6 +1186,10 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLTYPE_UINT|CTLF
|
||||
&SCTP_BASE_SYSCTL(sctp_add_more_threshold), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_ADD_MORE_ON_OUTPUT_DESC);
|
||||
|
||||
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, incoming_streams, CTLTYPE_UINT|CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_INCOMING_STREAMS_DESC);
|
||||
|
||||
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, outgoing_streams, CTLTYPE_UINT|CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_OUTGOING_STREAMS_DESC);
|
||||
@ -1515,6 +1525,10 @@ void sysctl_setup_sctp(void)
|
||||
&SCTP_BASE_SYSCTL(sctp_add_more_threshold), 0, sysctl_sctp_check,
|
||||
SCTPCTL_ADD_MORE_ON_OUTPUT_DESC);
|
||||
|
||||
sysctl_add_oid(&sysctl_oid_top, "incoming_streams", CTLTYPE_INT|CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default), 0, sysctl_sctp_check,
|
||||
SCTPCTL_INCOMING_STREAMS_DESC);
|
||||
|
||||
sysctl_add_oid(&sysctl_oid_top, "outgoing_streams", CTLTYPE_INT|CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), 0, sysctl_sctp_check,
|
||||
SCTPCTL_OUTGOING_STREAMS_DESC);
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 237565 2012-06-25 17:15:09Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 252779 2013-07-05 10:08:49Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_SYSCTL_H_
|
||||
@ -79,6 +79,7 @@ struct sctp_sysctl {
|
||||
uint32_t sctp_path_rtx_max_default;
|
||||
uint32_t sctp_path_pf_threshold;
|
||||
uint32_t sctp_add_more_threshold;
|
||||
uint32_t sctp_nr_incoming_streams_default;
|
||||
uint32_t sctp_nr_outgoing_streams_default;
|
||||
uint32_t sctp_cmt_on_off;
|
||||
uint32_t sctp_cmt_use_dac;
|
||||
@ -339,6 +340,12 @@ struct sctp_sysctl {
|
||||
#define SCTPCTL_ADD_MORE_ON_OUTPUT_MAX 0xFFFFFFFF
|
||||
#define SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT SCTP_DEFAULT_ADD_MORE
|
||||
|
||||
/* incoming_streams: Default number of incoming streams */
|
||||
#define SCTPCTL_INCOMING_STREAMS_DESC "Default number of incoming streams"
|
||||
#define SCTPCTL_INCOMING_STREAMS_MIN 1
|
||||
#define SCTPCTL_INCOMING_STREAMS_MAX 65535
|
||||
#define SCTPCTL_INCOMING_STREAMS_DEFAULT SCTP_ISTREAM_INITIAL
|
||||
|
||||
/* outgoing_streams: Default number of outgoing streams */
|
||||
#define SCTPCTL_OUTGOING_STREAMS_DESC "Default number of outgoing streams"
|
||||
#define SCTPCTL_OUTGOING_STREAMS_MIN 1
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 246588 2013-02-09 08:27:08Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 257359 2013-10-29 20:04:50Z tuexen $");
|
||||
#endif
|
||||
|
||||
#define _IP_VHL
|
||||
@ -442,7 +442,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
|
||||
}
|
||||
}
|
||||
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
|
||||
if (chk->pr_sctp_on) {
|
||||
if (PR_SCTP_ENABLED(chk->flags)) {
|
||||
if (asoc->pr_sctp_cnt != 0)
|
||||
asoc->pr_sctp_cnt--;
|
||||
}
|
||||
@ -551,7 +551,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) {
|
||||
if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.TSN_seq)) {
|
||||
/* Strange case our list got out of order? */
|
||||
SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x",
|
||||
SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x\n",
|
||||
(unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq);
|
||||
recovery_cnt++;
|
||||
#ifdef INVARIANTS
|
||||
|
@ -96,8 +96,11 @@ void sctp_audit_retranmission_queue(struct sctp_association *);
|
||||
void sctp_iterator_timer(struct sctp_iterator *it);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
void sctp_slowtimo();
|
||||
|
||||
#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
|
||||
void sctp_slowtimo(void);
|
||||
#else
|
||||
void sctp_gc(struct inpcbinfo *);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 242327 2012-10-29 20:47:32Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 255160 2013-09-02 22:48:41Z tuexen $");
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET_SCTP_UIO_H_
|
||||
@ -691,10 +691,6 @@ struct sctp_hmacalgo {
|
||||
#define SCTP_AUTH_HMAC_ID_RSVD 0x0000
|
||||
#define SCTP_AUTH_HMAC_ID_SHA1 0x0001 /* default, mandatory */
|
||||
#define SCTP_AUTH_HMAC_ID_SHA256 0x0003
|
||||
#define SCTP_AUTH_HMAC_ID_SHA224 0x0004
|
||||
#define SCTP_AUTH_HMAC_ID_SHA384 0x0005
|
||||
#define SCTP_AUTH_HMAC_ID_SHA512 0x0006
|
||||
|
||||
|
||||
/* SCTP_AUTH_ACTIVE_KEY / SCTP_AUTH_DELETE_KEY */
|
||||
struct sctp_authkeyid {
|
||||
@ -1174,7 +1170,11 @@ union sctp_sockstore {
|
||||
struct xsctp_inpcb {
|
||||
uint32_t last;
|
||||
uint32_t flags;
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000048
|
||||
uint32_t features;
|
||||
#else
|
||||
uint64_t features;
|
||||
#endif
|
||||
uint32_t total_sends;
|
||||
uint32_t total_recvs;
|
||||
uint32_t total_nospaces;
|
||||
@ -1185,7 +1185,11 @@ struct xsctp_inpcb {
|
||||
#if defined(__Windows__)
|
||||
uint16_t padding;
|
||||
#endif
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000048
|
||||
uint32_t extra_padding[32]; /* future */
|
||||
#else
|
||||
uint32_t extra_padding[31]; /* future */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct xsctp_tcb {
|
||||
@ -1328,7 +1332,7 @@ sctp_sorecvmsg(struct socket *so,
|
||||
#if !(defined(_KERNEL)) && !(defined(__Userspace__))
|
||||
|
||||
__BEGIN_DECLS
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000000
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 902000
|
||||
int sctp_peeloff __P((int, sctp_assoc_t));
|
||||
int sctp_bindx __P((int, struct sockaddr *, int, int));
|
||||
int sctp_connectx __P((int, const struct sockaddr *, int, sctp_assoc_t *));
|
||||
|
@ -97,17 +97,21 @@ getwintimeofday(struct timeval *tv)
|
||||
int
|
||||
Win_getifaddrs(struct ifaddrs** interfaces)
|
||||
{
|
||||
#if defined(INET) || defined(INET6)
|
||||
DWORD Err, AdapterAddrsSize;
|
||||
int count;
|
||||
PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt;
|
||||
struct ifaddrs *ifa;
|
||||
#endif
|
||||
#if defined(INET)
|
||||
struct sockaddr_in *addr;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
struct sockaddr_in6 *addr6;
|
||||
#endif
|
||||
#if defined(INET) || defined(INET6)
|
||||
count = 0;
|
||||
#endif
|
||||
#if defined(INET)
|
||||
AdapterAddrsSize = 0;
|
||||
if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &AdapterAddrsSize)) != 0) {
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 246687 2013-02-11 21:02:49Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 259943 2013-12-27 13:07:00Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -76,6 +76,8 @@ void
|
||||
sctp_init(uint16_t port,
|
||||
int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
|
||||
void (*debug_printf)(const char *format, ...))
|
||||
#elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
|
||||
sctp_init(struct protosw *pp SCTP_UNUSED, struct domain *dp SCTP_UNUSED)
|
||||
#else
|
||||
sctp_init(void)
|
||||
#endif
|
||||
@ -84,16 +86,22 @@ sctp_init(void)
|
||||
u_long sb_max_adj;
|
||||
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
#if defined(__Userspace_os_Windows)
|
||||
#if defined(INET) || defined(INET6)
|
||||
WSADATA wsaData;
|
||||
int Ret;
|
||||
|
||||
if ((Ret = WSAStartup(MAKEWORD(2,2), &wsaData))!=0) {
|
||||
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
|
||||
SCTP_PRINTF("WSAStartup failed\n");
|
||||
exit (-1);
|
||||
}
|
||||
#endif
|
||||
InitializeConditionVariable(&accept_cond);
|
||||
InitializeCriticalSection(&accept_mtx);
|
||||
#else
|
||||
pthread_cond_init(&accept_cond, NULL);
|
||||
pthread_mutex_init(&accept_mtx, NULL);
|
||||
#endif
|
||||
#endif
|
||||
/* Initialize and modify the sysctled variables */
|
||||
sctp_init_sysctls();
|
||||
@ -171,8 +179,7 @@ sctp_init(void)
|
||||
#if defined(__APPLE__)
|
||||
SCTP_BASE_VAR(sctp_main_timer_ticks) = 0;
|
||||
sctp_start_main_timer();
|
||||
sctp_address_monitor_start();
|
||||
sctp_over_udp_start();
|
||||
timeout(sctp_delayed_startup, NULL, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -180,6 +187,7 @@ void
|
||||
sctp_finish(void)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
untimeout(sctp_delayed_startup, NULL);
|
||||
sctp_over_udp_stop();
|
||||
sctp_address_monitor_stop();
|
||||
sctp_stop_main_timer();
|
||||
@ -199,6 +207,7 @@ sctp_finish(void)
|
||||
if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
|
||||
#if defined(__Userspace_os_Windows)
|
||||
WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw), INFINITE);
|
||||
CloseHandle(SCTP_BASE_VAR(recvthreadraw));
|
||||
#else
|
||||
pthread_join(SCTP_BASE_VAR(recvthreadraw), NULL);
|
||||
#endif
|
||||
@ -206,6 +215,7 @@ sctp_finish(void)
|
||||
if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
|
||||
#if defined(__Userspace_os_Windows)
|
||||
WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp), INFINITE);
|
||||
CloseHandle(SCTP_BASE_VAR(recvthreadudp));
|
||||
#else
|
||||
pthread_join(SCTP_BASE_VAR(recvthreadudp), NULL);
|
||||
#endif
|
||||
@ -215,6 +225,7 @@ sctp_finish(void)
|
||||
if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
|
||||
#if defined(__Userspace_os_Windows)
|
||||
WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw6), INFINITE);
|
||||
CloseHandle(SCTP_BASE_VAR(recvthreadraw6));
|
||||
#else
|
||||
pthread_join(SCTP_BASE_VAR(recvthreadraw6), NULL);
|
||||
#endif
|
||||
@ -222,6 +233,7 @@ sctp_finish(void)
|
||||
if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
|
||||
#if defined(__Userspace_os_Windows)
|
||||
WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp6), INFINITE);
|
||||
CloseHandle(SCTP_BASE_VAR(recvthreadudp6));
|
||||
#else
|
||||
pthread_join(SCTP_BASE_VAR(recvthreadudp6), NULL);
|
||||
#endif
|
||||
@ -230,13 +242,26 @@ sctp_finish(void)
|
||||
SCTP_BASE_VAR(timer_thread_should_exit) = 1;
|
||||
#if defined(__Userspace_os_Windows)
|
||||
WaitForSingleObject(SCTP_BASE_VAR(timer_thread), INFINITE);
|
||||
CloseHandle(SCTP_BASE_VAR(timer_thread));
|
||||
#else
|
||||
pthread_join(SCTP_BASE_VAR(timer_thread), NULL);
|
||||
#endif
|
||||
#endif
|
||||
sctp_pcb_finish();
|
||||
#if defined(__Userspace__)
|
||||
#if defined(__Userspace_os_Windows)
|
||||
DeleteConditionVariable(&accept_cond);
|
||||
DeleteCriticalSection(&accept_mtx);
|
||||
#else
|
||||
pthread_cond_destroy(&accept_cond);
|
||||
pthread_mutex_destroy(&accept_mtx);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__Windows__)
|
||||
sctp_finish_sysctls();
|
||||
#if defined(INET) || defined(INET6)
|
||||
WSACleanup();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -412,8 +437,10 @@ sctp_notify(struct sctp_inpcb *inp,
|
||||
(icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
|
||||
(icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
|
||||
(icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
|
||||
#ifdef __Panda__
|
||||
#if defined(__Panda__)
|
||||
(icmph->icmp_code == ICMP_UNREACH_ADMIN)) {
|
||||
#elif defined(__Userspace_os_NetBSD)
|
||||
(icmph->icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
|
||||
#else
|
||||
(icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
|
||||
#endif
|
||||
@ -1162,11 +1189,11 @@ sctp_disconnect(struct socket *so)
|
||||
}
|
||||
#if defined(__Userspace__)
|
||||
if (((so->so_options & SCTP_SO_LINGER) &&
|
||||
(so->so_linger == 0)) ||
|
||||
(so->so_linger == 0)) ||
|
||||
(so->so_rcv.sb_cc > 0)) {
|
||||
#else
|
||||
if (((so->so_options & SO_LINGER) &&
|
||||
(so->so_linger == 0)) ||
|
||||
(so->so_linger == 0)) ||
|
||||
(so->so_rcv.sb_cc > 0)) {
|
||||
#endif
|
||||
if (SCTP_GET_STATE(asoc) !=
|
||||
@ -1558,9 +1585,14 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
|
||||
{
|
||||
struct sctp_ifn *sctp_ifn;
|
||||
struct sctp_ifa *sctp_ifa;
|
||||
int loopback_scope, ipv4_local_scope, local_scope, site_scope;
|
||||
size_t actual;
|
||||
int ipv4_addr_legal, ipv6_addr_legal;
|
||||
int loopback_scope;
|
||||
#if defined(INET)
|
||||
int ipv4_local_scope, ipv4_addr_legal;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
int local_scope, site_scope, ipv6_addr_legal;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
int conn_addr_legal;
|
||||
#endif
|
||||
@ -1573,42 +1605,62 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
|
||||
if (stcb) {
|
||||
/* Turn on all the appropriate scope */
|
||||
loopback_scope = stcb->asoc.scope.loopback_scope;
|
||||
#if defined(INET)
|
||||
ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
|
||||
ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
local_scope = stcb->asoc.scope.local_scope;
|
||||
site_scope = stcb->asoc.scope.site_scope;
|
||||
ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
|
||||
ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
|
||||
#endif
|
||||
} else {
|
||||
/* Use generic values for endpoints. */
|
||||
loopback_scope = 1;
|
||||
#if defined(INET)
|
||||
ipv4_local_scope = 1;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
local_scope = 1;
|
||||
site_scope = 1;
|
||||
#endif
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
|
||||
#if defined(INET6)
|
||||
ipv6_addr_legal = 1;
|
||||
#endif
|
||||
#if defined(INET)
|
||||
if (SCTP_IPV6_V6ONLY(inp)) {
|
||||
ipv4_addr_legal = 0;
|
||||
} else {
|
||||
ipv4_addr_legal = 1;
|
||||
}
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
conn_addr_legal = 0;
|
||||
#endif
|
||||
} else {
|
||||
#if defined(INET6)
|
||||
ipv6_addr_legal = 0;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
|
||||
conn_addr_legal = 1;
|
||||
#if defined(INET)
|
||||
ipv4_addr_legal = 0;
|
||||
#endif
|
||||
} else {
|
||||
conn_addr_legal = 0;
|
||||
#if defined(INET)
|
||||
ipv4_addr_legal = 1;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#if defined(INET)
|
||||
ipv4_addr_legal = 1;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -3391,7 +3443,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
|
||||
if (stcb) {
|
||||
/* simply copy out the sockaddr_storage... */
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
len = *optsize;
|
||||
#ifdef HAVE_SA_LEN
|
||||
@ -3954,7 +4006,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
}
|
||||
}
|
||||
if (error == 0) {
|
||||
*optsize = sizeof(struct sctp_paddrparams);
|
||||
*optsize = sizeof(struct sctp_udpencaps);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -4726,7 +4778,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
sctp_hmaclist_t *hmaclist;
|
||||
uint16_t hmacid;
|
||||
uint32_t i;
|
||||
size_t found;
|
||||
|
||||
SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
|
||||
if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
|
||||
@ -4751,14 +4802,14 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
goto sctp_set_hmac_done;
|
||||
}
|
||||
}
|
||||
found = 0;
|
||||
for (i = 0; i < hmaclist->num_algo; i++) {
|
||||
if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
|
||||
/* already in list */
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (i == hmaclist->num_algo) {
|
||||
/* not found in list */
|
||||
sctp_free_hmaclist(hmaclist);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
@ -5592,11 +5643,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
|
||||
}
|
||||
net->dest_state |= SCTP_ADDR_NO_PMTUD;
|
||||
if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
|
||||
net->mtu = paddrp->spp_pathmtu + ovh;
|
||||
if (net->mtu < stcb->asoc.smallest_mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
}
|
||||
net->mtu = paddrp->spp_pathmtu + ovh;
|
||||
if (net->mtu < stcb->asoc.smallest_mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
}
|
||||
}
|
||||
if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
|
||||
@ -5717,11 +5766,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
|
||||
}
|
||||
net->dest_state |= SCTP_ADDR_NO_PMTUD;
|
||||
if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
|
||||
net->mtu = paddrp->spp_pathmtu + ovh;
|
||||
if (net->mtu < stcb->asoc.smallest_mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
}
|
||||
net->mtu = paddrp->spp_pathmtu + ovh;
|
||||
if (net->mtu < stcb->asoc.smallest_mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
}
|
||||
}
|
||||
sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
|
||||
@ -7754,7 +7801,7 @@ sctp_peeraddr(struct socket *so, struct mbuf *nam)
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
|
||||
struct pr_usrreqs sctp_usrreqs = {
|
||||
#if __FreeBSD_version >= 600000
|
||||
#if defined(__FreeBSD__)
|
||||
.pru_abort = sctp_abort,
|
||||
.pru_accept = sctp_accept,
|
||||
.pru_attach = sctp_attach,
|
||||
@ -7778,45 +7825,51 @@ struct pr_usrreqs sctp_usrreqs = {
|
||||
.pru_sockaddr = sctp_ingetaddr,
|
||||
.pru_sosend = sctp_sosend,
|
||||
.pru_soreceive = sctp_soreceive
|
||||
#else
|
||||
#elif defined(__APPLE__)
|
||||
.pru_abort = sctp_abort,
|
||||
.pru_accept = sctp_accept,
|
||||
.pru_attach = sctp_attach,
|
||||
.pru_bind = sctp_bind,
|
||||
.pru_connect = sctp_connect,
|
||||
.pru_connect2 = pru_connect2_notsupp,
|
||||
.pru_control = in_control,
|
||||
.pru_detach = sctp_detach,
|
||||
.pru_disconnect = sctp_disconnect,
|
||||
.pru_listen = sctp_listen,
|
||||
.pru_peeraddr = sctp_peeraddr,
|
||||
.pru_rcvd = NULL,
|
||||
.pru_rcvoob = pru_rcvoob_notsupp,
|
||||
.pru_send = sctp_sendm,
|
||||
.pru_sense = pru_sense_null,
|
||||
.pru_shutdown = sctp_shutdown,
|
||||
.pru_sockaddr = sctp_ingetaddr,
|
||||
.pru_sosend = sctp_sosend,
|
||||
.pru_soreceive = sctp_soreceive,
|
||||
.pru_sopoll = sopoll
|
||||
#elif defined(__Windows__)
|
||||
sctp_abort,
|
||||
sctp_accept,
|
||||
sctp_attach,
|
||||
sctp_bind,
|
||||
sctp_connect,
|
||||
pru_connect2_notsupp,
|
||||
#if defined(__Windows__)
|
||||
NULL,
|
||||
NULL,
|
||||
#else
|
||||
in_control,
|
||||
sctp_detach,
|
||||
#endif
|
||||
sctp_disconnect,
|
||||
sctp_listen,
|
||||
sctp_peeraddr,
|
||||
NULL,
|
||||
pru_rcvoob_notsupp,
|
||||
#if defined(__Windows__)
|
||||
NULL,
|
||||
#else
|
||||
sctp_sendm,
|
||||
#endif
|
||||
pru_sense_null,
|
||||
sctp_shutdown,
|
||||
#if defined(__Windows__)
|
||||
sctp_flush,
|
||||
#endif
|
||||
sctp_ingetaddr,
|
||||
sctp_sosend,
|
||||
sctp_soreceive,
|
||||
#if defined(__Windows__)
|
||||
sopoll_generic,
|
||||
NULL,
|
||||
sctp_close
|
||||
#else
|
||||
sopoll
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
#elif !defined(__Panda__) && !defined(__Userspace__)
|
||||
|
@ -399,7 +399,7 @@ int sctp_detach(struct socket *so);
|
||||
#endif
|
||||
int sctp_disconnect(struct socket *so);
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000000
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 902000
|
||||
void sctp_ctlinput __P((int, struct sockaddr *, void *));
|
||||
int sctp_ctloutput __P((struct socket *, struct sockopt *));
|
||||
#ifdef INET
|
||||
@ -427,7 +427,7 @@ void sctp_input(struct mbuf *,...);
|
||||
void *sctp_ctlinput(int, struct sockaddr *, void *);
|
||||
int sctp_ctloutput(int, struct socket *, int, int, struct mbuf **);
|
||||
#endif
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000000
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 902000
|
||||
void sctp_drain __P((void));
|
||||
#else
|
||||
void sctp_drain(void);
|
||||
@ -436,18 +436,18 @@ void sctp_drain(void);
|
||||
void sctp_init(uint16_t,
|
||||
int (*)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
|
||||
void (*)(const char *, ...));
|
||||
#else
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000000
|
||||
#elif defined(__FreeBSD__) && __FreeBSD_version < 902000
|
||||
void sctp_init __P((void));
|
||||
#elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
|
||||
void sctp_init(struct protosw *pp, struct domain *dp);
|
||||
#else
|
||||
void sctp_init(void);
|
||||
#endif
|
||||
#endif
|
||||
void sctp_finish(void);
|
||||
#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
|
||||
int sctp_flush(struct socket *, int);
|
||||
#endif
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000000
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 902000
|
||||
int sctp_shutdown __P((struct socket *));
|
||||
void sctp_notify __P((struct sctp_inpcb *, struct ip *ip, struct sctphdr *,
|
||||
struct sockaddr *, struct sctp_tcb *,
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 247412 2013-02-27 19:51:47Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 259943 2013-12-27 13:07:00Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -2721,7 +2721,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
|
||||
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
|
||||
notif_len = sizeof(struct sctp_assoc_change);
|
||||
if (abort != NULL) {
|
||||
abort_len = htons(abort->ch.chunk_length);
|
||||
abort_len = ntohs(abort->ch.chunk_length);
|
||||
} else {
|
||||
abort_len = 0;
|
||||
}
|
||||
@ -2756,7 +2756,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
|
||||
if (stcb->asoc.peer_supports_prsctp) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
|
||||
}
|
||||
if (stcb->asoc.peer_supports_auth) {
|
||||
if (stcb->asoc.peer_supports_auth) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
|
||||
}
|
||||
if (stcb->asoc.peer_supports_asconf) {
|
||||
@ -2774,17 +2774,17 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
|
||||
}
|
||||
SCTP_BUF_LEN(m_notify) = sac->sac_length;
|
||||
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
|
||||
0, 0, stcb->asoc.context, 0, 0, 0,
|
||||
m_notify);
|
||||
0, 0, stcb->asoc.context, 0, 0, 0,
|
||||
m_notify);
|
||||
if (control != NULL) {
|
||||
control->length = SCTP_BUF_LEN(m_notify);
|
||||
/* not that we need this */
|
||||
control->tail_mbuf = m_notify;
|
||||
control->spec_flags = M_NOTIFICATION;
|
||||
sctp_add_to_readq(stcb->sctp_ep, stcb,
|
||||
control,
|
||||
&stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD,
|
||||
so_locked);
|
||||
control,
|
||||
&stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD,
|
||||
so_locked);
|
||||
} else {
|
||||
sctp_m_freem(m_notify);
|
||||
}
|
||||
@ -2807,8 +2807,14 @@ set_error:
|
||||
stcb->sctp_socket->so_error = ECONNRESET;
|
||||
}
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED);
|
||||
stcb->sctp_socket->so_error = ECONNABORTED;
|
||||
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
|
||||
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
|
||||
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT);
|
||||
stcb->sctp_socket->so_error = ETIMEDOUT;
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED);
|
||||
stcb->sctp_socket->so_error = ECONNABORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Wake ANY sleepers */
|
||||
@ -2929,10 +2935,10 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
|
||||
/* not that we need this */
|
||||
control->tail_mbuf = m_notify;
|
||||
sctp_add_to_readq(stcb->sctp_ep, stcb,
|
||||
control,
|
||||
&stcb->sctp_socket->so_rcv, 1,
|
||||
SCTP_READ_LOCK_NOT_HELD,
|
||||
SCTP_SO_NOT_LOCKED);
|
||||
control,
|
||||
&stcb->sctp_socket->so_rcv, 1,
|
||||
SCTP_READ_LOCK_NOT_HELD,
|
||||
SCTP_SO_NOT_LOCKED);
|
||||
}
|
||||
|
||||
|
||||
@ -3611,7 +3617,7 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro
|
||||
return;
|
||||
}
|
||||
if (chunk != NULL) {
|
||||
chunk_len = htons(chunk->ch.chunk_length);
|
||||
chunk_len = ntohs(chunk->ch.chunk_length);
|
||||
} else {
|
||||
chunk_len = 0;
|
||||
}
|
||||
@ -3684,8 +3690,8 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
|
||||
}
|
||||
#endif
|
||||
if (stcb && ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) ||
|
||||
(stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED))) {
|
||||
if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) ||
|
||||
(stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED)) {
|
||||
if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) ||
|
||||
(notification == SCTP_NOTIFY_INTERFACE_UP) ||
|
||||
(notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) {
|
||||
@ -3704,7 +3710,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
}
|
||||
if (stcb->asoc.peer_supports_auth == 0) {
|
||||
sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
|
||||
NULL, so_locked);
|
||||
NULL, so_locked);
|
||||
}
|
||||
break;
|
||||
case SCTP_NOTIFY_ASSOC_DOWN:
|
||||
@ -3755,7 +3761,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
}
|
||||
case SCTP_NOTIFY_SPECIAL_SP_FAIL:
|
||||
sctp_notify_send_failed2(stcb, error,
|
||||
(struct sctp_stream_queue_pending *)data, so_locked);
|
||||
(struct sctp_stream_queue_pending *)data, so_locked);
|
||||
break;
|
||||
case SCTP_NOTIFY_SENT_DG_FAIL:
|
||||
sctp_notify_send_failed(stcb, 1, error,
|
||||
@ -3763,7 +3769,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
break;
|
||||
case SCTP_NOTIFY_UNSENT_DG_FAIL:
|
||||
sctp_notify_send_failed(stcb, 0, error,
|
||||
(struct sctp_tmit_chunk *)data, so_locked);
|
||||
(struct sctp_tmit_chunk *)data, so_locked);
|
||||
break;
|
||||
case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
|
||||
{
|
||||
@ -3774,16 +3780,16 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
break;
|
||||
}
|
||||
case SCTP_NOTIFY_ASSOC_LOC_ABORTED:
|
||||
if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
|
||||
((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED))) {
|
||||
if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
|
||||
((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
|
||||
sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked);
|
||||
} else {
|
||||
sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked);
|
||||
}
|
||||
break;
|
||||
case SCTP_NOTIFY_ASSOC_REM_ABORTED:
|
||||
if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
|
||||
((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED))) {
|
||||
if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
|
||||
((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
|
||||
sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked);
|
||||
} else {
|
||||
sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked);
|
||||
@ -3793,7 +3799,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked);
|
||||
if (stcb->asoc.peer_supports_auth == 0) {
|
||||
sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
|
||||
NULL, so_locked);
|
||||
NULL, so_locked);
|
||||
}
|
||||
break;
|
||||
case SCTP_NOTIFY_STR_RESET_SEND:
|
||||
@ -3804,7 +3810,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
break;
|
||||
case SCTP_NOTIFY_STR_RESET_FAILED_OUT:
|
||||
sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
|
||||
(SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_FAILED));
|
||||
(SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_FAILED));
|
||||
break;
|
||||
case SCTP_NOTIFY_STR_RESET_DENIED_OUT:
|
||||
sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
|
||||
@ -3812,7 +3818,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
break;
|
||||
case SCTP_NOTIFY_STR_RESET_FAILED_IN:
|
||||
sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
|
||||
(SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_FAILED));
|
||||
(SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_FAILED));
|
||||
break;
|
||||
case SCTP_NOTIFY_STR_RESET_DENIED_IN:
|
||||
sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
|
||||
@ -3824,29 +3830,29 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
break;
|
||||
case SCTP_NOTIFY_ASCONF_DELETE_IP:
|
||||
sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
|
||||
error);
|
||||
error);
|
||||
break;
|
||||
case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
|
||||
sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
|
||||
error);
|
||||
error);
|
||||
break;
|
||||
case SCTP_NOTIFY_PEER_SHUTDOWN:
|
||||
sctp_notify_shutdown_event(stcb);
|
||||
break;
|
||||
case SCTP_NOTIFY_AUTH_NEW_KEY:
|
||||
sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error,
|
||||
(uint16_t)(uintptr_t)data,
|
||||
so_locked);
|
||||
(uint16_t)(uintptr_t)data,
|
||||
so_locked);
|
||||
break;
|
||||
case SCTP_NOTIFY_AUTH_FREE_KEY:
|
||||
sctp_notify_authentication(stcb, SCTP_AUTH_FREE_KEY, error,
|
||||
(uint16_t)(uintptr_t)data,
|
||||
so_locked);
|
||||
(uint16_t)(uintptr_t)data,
|
||||
so_locked);
|
||||
break;
|
||||
case SCTP_NOTIFY_NO_PEER_AUTH:
|
||||
sctp_notify_authentication(stcb, SCTP_AUTH_NO_AUTH, error,
|
||||
(uint16_t)(uintptr_t)data,
|
||||
so_locked);
|
||||
(uint16_t)(uintptr_t)data,
|
||||
so_locked);
|
||||
break;
|
||||
case SCTP_NOTIFY_SENDER_DRY:
|
||||
sctp_notify_sender_dry_event(stcb, so_locked);
|
||||
@ -4155,7 +4161,7 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
if (stcb == NULL) {
|
||||
/* Got to have a TCB */
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
|
||||
if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
|
||||
if (LIST_EMPTY(&inp->sctp_asoc_list)) {
|
||||
#if defined(__APPLE__)
|
||||
if (!so_locked) {
|
||||
SCTP_SOCKET_LOCK(so, 1);
|
||||
@ -4222,7 +4228,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
|
||||
SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue);
|
||||
/* Generate a TO address for future reference */
|
||||
if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
|
||||
if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
|
||||
if (LIST_EMPTY(&inp->sctp_asoc_list)) {
|
||||
#if defined(__APPLE__)
|
||||
SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1);
|
||||
#endif
|
||||
@ -4737,7 +4743,7 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
char *buffer;
|
||||
struct sctp_rcvinfo rcv;
|
||||
union sctp_sockstore addr;
|
||||
int flags = 0;
|
||||
int flags;
|
||||
|
||||
if ((buffer = malloc(control->length)) == NULL) {
|
||||
return;
|
||||
@ -4770,24 +4776,22 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
addr.sin6 = control->whoFrom->ro._l_addr.sin6;
|
||||
break;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
case AF_CONN:
|
||||
addr.sconn = control->whoFrom->ro._l_addr.sconn;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
addr.sa = control->whoFrom->ro._l_addr.sa;
|
||||
break;
|
||||
}
|
||||
flags = MSG_EOR;
|
||||
if (control->spec_flags & M_NOTIFICATION) {
|
||||
flags |= MSG_NOTIFICATION;
|
||||
}
|
||||
if (control->spec_flags & M_EOR) {
|
||||
flags |= MSG_EOR;
|
||||
}
|
||||
inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info);
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_subtract_int(&stcb->asoc.refcnt, 1);
|
||||
sctp_free_remote_addr(control->whoFrom);
|
||||
control->whoFrom = NULL;
|
||||
sctp_m_freem(control->data);
|
||||
control->data = NULL;
|
||||
control->length = 0;
|
||||
@ -4950,24 +4954,32 @@ sctp_append_to_readq(struct sctp_inpcb *inp,
|
||||
* is populated in the outbound sinfo structure from the true cumack
|
||||
* if the association exists...
|
||||
*/
|
||||
control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack;
|
||||
#if defined(__Userspace__)
|
||||
if (inp->recv_callback) {
|
||||
if (control->end_added == 1) {
|
||||
uint32_t pd_point, length;
|
||||
|
||||
length = control->length;
|
||||
if (stcb != NULL && stcb->sctp_socket != NULL) {
|
||||
pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
|
||||
stcb->sctp_ep->partial_delivery_point);
|
||||
} else {
|
||||
pd_point = inp->partial_delivery_point;
|
||||
}
|
||||
if ((control->end_added == 1) || (length >= pd_point)) {
|
||||
struct socket *so;
|
||||
char *buffer;
|
||||
struct sctp_rcvinfo rcv;
|
||||
union sctp_sockstore addr;
|
||||
int flags = 0;
|
||||
int flags;
|
||||
|
||||
if ((buffer = malloc(control->length)) == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
so = inp->sctp_socket;
|
||||
so = stcb->sctp_socket;
|
||||
for (m = control->data; m; m = SCTP_BUF_NEXT(m)) {
|
||||
sctp_sbfree(control, control->stcb, &so->so_rcv, m);
|
||||
}
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
m_copydata(control->data, 0, control->length, buffer);
|
||||
memset(&rcv, 0, sizeof(struct sctp_rcvinfo));
|
||||
rcv.rcv_sid = control->sinfo_stream;
|
||||
@ -4990,35 +5002,42 @@ sctp_append_to_readq(struct sctp_inpcb *inp,
|
||||
addr.sin6 = control->whoFrom->ro._l_addr.sin6;
|
||||
break;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
case AF_CONN:
|
||||
addr.sconn = control->whoFrom->ro._l_addr.sconn;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
addr.sa = control->whoFrom->ro._l_addr.sa;
|
||||
break;
|
||||
}
|
||||
flags = 0;
|
||||
if (control->end_added == 1) {
|
||||
flags |= MSG_EOR;
|
||||
}
|
||||
if (control->spec_flags & M_NOTIFICATION) {
|
||||
flags |= MSG_NOTIFICATION;
|
||||
}
|
||||
if (control->spec_flags & M_EOR) {
|
||||
flags |= MSG_EOR;
|
||||
}
|
||||
inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info);
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_subtract_int(&stcb->asoc.refcnt, 1);
|
||||
sctp_m_freem(control->data);
|
||||
control->data = NULL;
|
||||
control->tail_mbuf = NULL;
|
||||
control->length = 0;
|
||||
sctp_free_a_readq(stcb, control);
|
||||
if (control->end_added) {
|
||||
sctp_free_remote_addr(control->whoFrom);
|
||||
control->whoFrom = NULL;
|
||||
sctp_free_a_readq(stcb, control);
|
||||
} else {
|
||||
control->some_taken = 1;
|
||||
}
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
inp->recv_callback(so, addr, buffer, length, rcv, flags, inp->ulp_info);
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_subtract_int(&stcb->asoc.refcnt, 1);
|
||||
}
|
||||
if (inp)
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack;
|
||||
if (inp) {
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
}
|
||||
@ -5272,7 +5291,6 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
|
||||
chk->rec.data.TSN_seq = stcb->asoc.sending_seq++;
|
||||
#endif
|
||||
stcb->asoc.pr_sctp_cnt++;
|
||||
chk->pr_sctp_on = 1;
|
||||
TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
|
||||
stcb->asoc.sent_queue_cnt++;
|
||||
stcb->asoc.pr_sctp_cnt++;
|
||||
@ -5431,10 +5449,10 @@ sctp_get_ifa_hash_val(struct sockaddr *addr)
|
||||
case AF_CONN:
|
||||
{
|
||||
struct sockaddr_conn *sconn;
|
||||
uint64_t temp;
|
||||
uintptr_t temp;
|
||||
|
||||
sconn = (struct sockaddr_conn *)addr;
|
||||
temp = (uint64_t)sconn->sconn_addr;
|
||||
temp = (uintptr_t)sconn->sconn_addr;
|
||||
return ((uint32_t)(temp ^ (temp >> 16)));
|
||||
}
|
||||
#endif
|
||||
@ -5704,7 +5722,7 @@ sctp_sorecvmsg(struct socket *so,
|
||||
if (rwnd_req < SCTP_MIN_RWND)
|
||||
rwnd_req = SCTP_MIN_RWND;
|
||||
in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) &SCTP_RECV_RWND_LOGGING_ENABLE) {
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
|
||||
#if defined(__APPLE__)
|
||||
#if defined(APPLE_LEOPARD)
|
||||
sctp_misc_ints(SCTP_SORECV_ENTER,
|
||||
@ -6459,8 +6477,8 @@ sctp_sorecvmsg(struct socket *so,
|
||||
#else
|
||||
if ((uio->uio_resid == 0) ||
|
||||
#endif
|
||||
((in_eeor_mode) && (copied_so_far >= max(so->so_rcv.sb_lowat, 1)))
|
||||
) {
|
||||
((in_eeor_mode) &&
|
||||
(copied_so_far >= (uint32_t)max(so->so_rcv.sb_lowat, 1)))) {
|
||||
goto release;
|
||||
}
|
||||
/*
|
||||
@ -6980,7 +6998,7 @@ sctp_hashinit_flags(int elements, struct malloc_type *type,
|
||||
hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl));
|
||||
else {
|
||||
#ifdef INVARIANTS
|
||||
SCTP_PRINTF("flag incorrect in hashinit_flags");
|
||||
SCTP_PRINTF("flag incorrect in hashinit_flags.\n");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
@ -7004,7 +7022,7 @@ sctp_hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask)
|
||||
hashtbl = vhashtbl;
|
||||
for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++)
|
||||
if (!LIST_EMPTY(hp)) {
|
||||
SCTP_PRINTF("hashdestroy: hash not empty");
|
||||
SCTP_PRINTF("hashdestroy: hash not empty.\n");
|
||||
return;
|
||||
}
|
||||
FREE(hashtbl, type);
|
||||
@ -7466,8 +7484,13 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
|
||||
int
|
||||
sctp_local_addr_count(struct sctp_tcb *stcb)
|
||||
{
|
||||
int loopback_scope, ipv4_local_scope, local_scope, site_scope;
|
||||
int ipv4_addr_legal, ipv6_addr_legal;
|
||||
int loopback_scope;
|
||||
#if defined(INET)
|
||||
int ipv4_local_scope, ipv4_addr_legal;
|
||||
#endif
|
||||
#if defined (INET6)
|
||||
int local_scope, site_scope, ipv6_addr_legal;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
int conn_addr_legal;
|
||||
#endif
|
||||
@ -7478,11 +7501,15 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
|
||||
|
||||
/* Turn on all the appropriate scopes */
|
||||
loopback_scope = stcb->asoc.scope.loopback_scope;
|
||||
#if defined(INET)
|
||||
ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
|
||||
ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
local_scope = stcb->asoc.scope.local_scope;
|
||||
site_scope = stcb->asoc.scope.site_scope;
|
||||
ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
|
||||
ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
|
||||
#endif
|
||||
#if defined(__Userspace__)
|
||||
conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 243186 2012-11-17 20:04:04Z tuexen $");
|
||||
__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 257555 2013-11-02 20:12:19Z tuexen $");
|
||||
#endif
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
@ -178,7 +178,13 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
|
||||
}
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
#if __FreeBSD_version >= 800000
|
||||
#if __FreeBSD_version > 1000049
|
||||
SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
|
||||
"sctp6_input(): Packet of length %d received on %s with csum_flags 0x%b.\n",
|
||||
m->m_pkthdr.len,
|
||||
if_name(m->m_pkthdr.rcvif),
|
||||
(int)m->m_pkthdr.csum_flags, CSUM_BITS);
|
||||
#elif __FreeBSD_version >= 800000
|
||||
SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
|
||||
"sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
|
||||
m->m_pkthdr.len,
|
||||
@ -457,8 +463,10 @@ sctp6_notify(struct sctp_inpcb *inp,
|
||||
(icmph->icmp6_code == ICMP_UNREACH_ISOLATED) ||
|
||||
(icmph->icmp6_code == ICMP_UNREACH_NET_PROHIB) ||
|
||||
(icmph->icmp6_code == ICMP_UNREACH_HOST_PROHIB) ||
|
||||
#ifdef __Panda__
|
||||
#if defined(__Panda__)
|
||||
(icmph->icmp6_code == ICMP_UNREACH_ADMIN)) {
|
||||
#elif defined(__Userspace_os_NetBSD)
|
||||
(icmph->icmp6_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
|
||||
#else
|
||||
(icmph->icmp6_code == ICMP_UNREACH_FILTER_PROHIB)) {
|
||||
#endif
|
||||
@ -1090,18 +1098,11 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam,
|
||||
}
|
||||
}
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
if (!MODULE_GLOBAL(ip6_v6only)) {
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
/* convert v4-mapped into v4 addr and send */
|
||||
in6_sin6_2_sin(&sin, sin6);
|
||||
return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin,
|
||||
control, p));
|
||||
} else {
|
||||
/* mapped addresses aren't enabled */
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
|
||||
return (EINVAL);
|
||||
}
|
||||
/* convert v4-mapped into v4 addr and send */
|
||||
in6_sin6_2_sin(&sin, sin6);
|
||||
return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin, control, p));
|
||||
}
|
||||
#endif /* INET */
|
||||
connected_type:
|
||||
@ -1179,14 +1180,16 @@ sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p)
|
||||
uint32_t vrf_id;
|
||||
int error = 0;
|
||||
struct sctp_inpcb *inp;
|
||||
struct in6pcb *inp6;
|
||||
struct sctp_tcb *stcb;
|
||||
#ifdef INET
|
||||
struct in6pcb *inp6;
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct sockaddr_storage ss;
|
||||
#endif
|
||||
|
||||
#ifdef INET
|
||||
inp6 = (struct in6pcb *)so->so_pcb;
|
||||
#endif
|
||||
inp = (struct sctp_inpcb *)so->so_pcb;
|
||||
if (inp == NULL) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
|
||||
@ -1269,17 +1272,9 @@ sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p)
|
||||
}
|
||||
}
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
if (!MODULE_GLOBAL(ip6_v6only)) {
|
||||
/* convert v4-mapped into v4 addr */
|
||||
in6_sin6_2_sin((struct sockaddr_in *)&ss, sin6);
|
||||
addr = (struct sockaddr *)&ss;
|
||||
} else {
|
||||
/* mapped addresses aren't enabled */
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
SCTP_ASOC_CREATE_UNLOCK(inp);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
|
||||
return (EINVAL);
|
||||
}
|
||||
/* convert v4-mapped into v4 addr */
|
||||
in6_sin6_2_sin((struct sockaddr_in *)&ss, sin6);
|
||||
addr = (struct sockaddr *)&ss;
|
||||
}
|
||||
#endif /* INET */
|
||||
/* Now do we connect? */
|
||||
@ -1690,7 +1685,7 @@ sctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
|
||||
struct pr_usrreqs sctp6_usrreqs = {
|
||||
#if __FreeBSD_version >= 600000
|
||||
#if defined(__FreeBSD__)
|
||||
.pru_abort = sctp6_abort,
|
||||
.pru_accept = sctp_accept,
|
||||
.pru_attach = sctp6_attach,
|
||||
@ -1714,46 +1709,52 @@ struct pr_usrreqs sctp6_usrreqs = {
|
||||
.pru_sockaddr = sctp6_in6getaddr,
|
||||
.pru_sosend = sctp_sosend,
|
||||
.pru_soreceive = sctp_soreceive
|
||||
#else
|
||||
#elif defined(__APPLE__)
|
||||
.pru_abort = sctp6_abort,
|
||||
.pru_accept = sctp_accept,
|
||||
.pru_attach = sctp6_attach,
|
||||
.pru_bind = sctp6_bind,
|
||||
.pru_connect = sctp6_connect,
|
||||
.pru_connect2 = pru_connect2_notsupp,
|
||||
.pru_control = in6_control,
|
||||
.pru_detach = sctp6_detach,
|
||||
.pru_disconnect = sctp6_disconnect,
|
||||
.pru_listen = sctp_listen,
|
||||
.pru_peeraddr = sctp6_getpeeraddr,
|
||||
.pru_rcvd = NULL,
|
||||
.pru_rcvoob = pru_rcvoob_notsupp,
|
||||
.pru_send = sctp6_send,
|
||||
.pru_sense = pru_sense_null,
|
||||
.pru_shutdown = sctp_shutdown,
|
||||
.pru_sockaddr = sctp6_in6getaddr,
|
||||
.pru_sosend = sctp_sosend,
|
||||
.pru_soreceive = sctp_soreceive,
|
||||
.pru_sopoll = sopoll
|
||||
#elif defined(__Windows__)
|
||||
sctp6_abort,
|
||||
sctp_accept,
|
||||
sctp6_attach,
|
||||
sctp6_bind,
|
||||
sctp6_connect,
|
||||
pru_connect2_notsupp,
|
||||
#if defined(__Windows__)
|
||||
NULL,
|
||||
NULL,
|
||||
#else
|
||||
in6_control,
|
||||
sctp6_detach,
|
||||
#endif
|
||||
sctp6_disconnect,
|
||||
sctp_listen,
|
||||
sctp6_getpeeraddr,
|
||||
NULL,
|
||||
pru_rcvoob_notsupp,
|
||||
#if defined(__Windows__)
|
||||
NULL,
|
||||
#else
|
||||
sctp6_send,
|
||||
#endif
|
||||
pru_sense_null,
|
||||
sctp_shutdown,
|
||||
#if defined(__Windows__)
|
||||
sctp_flush,
|
||||
#endif
|
||||
sctp6_in6getaddr,
|
||||
sctp_sosend,
|
||||
sctp_soreceive,
|
||||
#if !defined(__Windows__)
|
||||
sopoll
|
||||
#else
|
||||
sopoll_generic,
|
||||
NULL,
|
||||
sctp6_close
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#elif !defined(__Panda__) && !defined(__Userspace__)
|
||||
|
@ -55,14 +55,14 @@ int sctp6_input(struct mbuf **, int *);
|
||||
int sctp6_input_with_port(struct mbuf **, int *, uint16_t);
|
||||
#elif defined(__Panda__)
|
||||
int sctp6_input (pakhandle_type *);
|
||||
#elif defined(__FreeBSD__) && __FreeBSD_version < 1000000
|
||||
#elif defined(__FreeBSD__) && __FreeBSD_version < 902000
|
||||
int sctp6_input __P((struct mbuf **, int *, int));
|
||||
int sctp6_input_with_port __P((struct mbuf **, int *, uint16_t));
|
||||
#else
|
||||
int sctp6_input(struct mbuf **, int *, int);
|
||||
int sctp6_input_with_port(struct mbuf **, int *, uint16_t);
|
||||
#endif
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 1000000
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 902000
|
||||
int sctp6_output
|
||||
__P((struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
|
||||
struct mbuf *, struct proc *));
|
||||
|
@ -33,11 +33,6 @@
|
||||
#include <stdlib.h>
|
||||
#if !defined (__Userspace_os_Windows)
|
||||
#include <stdint.h>
|
||||
#if !defined(__Userspace_os_FreeBSD)
|
||||
#if !defined(ANDROID)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <netinet/sctp_os_userspace.h>
|
||||
#endif
|
||||
#include <user_environment.h>
|
||||
|
@ -35,13 +35,6 @@
|
||||
|
||||
#include <user_route.h> /* was <net/route.h> */
|
||||
|
||||
#if defined(ANDROID)
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
/* missing defines in Android bionic libc/NDK */
|
||||
typedef uint16_t in_port_t;
|
||||
#endif
|
||||
|
||||
#define in6pcb inpcb /* for KAME src sync over BSD*'s */
|
||||
#define in6p_sp inp_sp /* for KAME src sync over BSD*'s */
|
||||
struct inpcbpolicy;
|
||||
@ -56,7 +49,6 @@ struct inpcbpolicy;
|
||||
*/
|
||||
LIST_HEAD(inpcbhead, inpcb);
|
||||
LIST_HEAD(inpcbporthead, inpcbport);
|
||||
typedef u_quad_t inp_gen_t;
|
||||
|
||||
/*
|
||||
* PCB with AF_INET6 null bind'ed laddr can receive AF_INET input packet.
|
||||
@ -176,7 +168,6 @@ struct inpcb {
|
||||
LIST_ENTRY(inpcb) inp_portlist;
|
||||
struct inpcbport *inp_phd; /* head of this list */
|
||||
#define inp_zero_size offsetof(struct inpcb, inp_gencnt)
|
||||
inp_gen_t inp_gencnt; /* generation count of this instance */
|
||||
struct mtx inp_mtx;
|
||||
|
||||
#define in6p_faddr inp_inc.inc6_faddr
|
||||
@ -205,26 +196,6 @@ struct inpcb {
|
||||
* don't concern ourselves with that possibility.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Interface exported to userland by various protocols which use inpcbs. Hack
|
||||
* alert -- only define if struct xsocket is in scope.
|
||||
*/
|
||||
#ifdef _SYS_SOCKETVAR_H_
|
||||
struct xinpcb {
|
||||
size_t xi_len; /* length of this structure */
|
||||
struct inpcb xi_inp;
|
||||
struct xsocket xi_socket;
|
||||
u_quad_t xi_alignment_hack;
|
||||
};
|
||||
|
||||
struct xinpgen {
|
||||
size_t xig_len; /* length of this structure */
|
||||
u_int xig_count; /* number of PCBs at this time */
|
||||
inp_gen_t xig_gen; /* generation count at this time */
|
||||
so_gen_t xig_sogen; /* socket generation count at this time */
|
||||
};
|
||||
#endif /* _SYS_SOCKETVAR_H_ */
|
||||
|
||||
struct inpcbport {
|
||||
LIST_ENTRY(inpcbport) phd_hash;
|
||||
struct inpcbhead phd_pcblist;
|
||||
@ -271,7 +242,6 @@ struct inpcbinfo {
|
||||
* Generation count--incremented each time a connection is allocated
|
||||
* or freed.
|
||||
*/
|
||||
u_quad_t ipi_gencnt;
|
||||
struct mtx ipi_mtx;
|
||||
|
||||
/*
|
||||
@ -376,12 +346,7 @@ extern struct callout ipport_tick_callout;
|
||||
void in_pcbpurgeif0(struct inpcbinfo *, struct ifnet *);
|
||||
int in_pcballoc(struct socket *, struct inpcbinfo *);
|
||||
int in_pcbbind(struct inpcb *, struct sockaddr *, struct ucred *);
|
||||
int in_pcbbind_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
|
||||
u_short *, struct ucred *);
|
||||
int in_pcbconnect(struct inpcb *, struct sockaddr *, struct ucred *);
|
||||
int in_pcbconnect_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
|
||||
u_short *, in_addr_t *, u_short *, struct inpcb **,
|
||||
struct ucred *);
|
||||
void in_pcbdetach(struct inpcb *);
|
||||
void in_pcbdisconnect(struct inpcb *);
|
||||
void in_pcbdrop(struct inpcb *);
|
||||
@ -399,8 +364,6 @@ void in_pcbrehash(struct inpcb *);
|
||||
void in_pcbsetsolabel(struct socket *so);
|
||||
int in_getpeeraddr(struct socket *so, struct sockaddr **nam);
|
||||
int in_getsockaddr(struct socket *so, struct sockaddr **nam);
|
||||
struct sockaddr *
|
||||
in_sockaddr(in_port_t port, struct in_addr *addr);
|
||||
void in_pcbsosetlabel(struct socket *so);
|
||||
void in_pcbremlists(struct inpcb *inp);
|
||||
void ipport_tick(void *xtp);
|
||||
|
@ -95,7 +95,7 @@ struct ip6_hdr {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_OpenBSD)
|
||||
#if !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_OpenBSD) && !defined(__Userspace_os_DragonFly)
|
||||
struct route_in6 {
|
||||
struct rtentry *ro_rt;
|
||||
struct llentry *ro_lle;
|
||||
|
@ -163,9 +163,9 @@ struct mbstat {
|
||||
* externally and attach it to the mbuf in a way similar to that of mbuf
|
||||
* clusters.
|
||||
*/
|
||||
#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */
|
||||
#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */
|
||||
#define MINCLSIZE (MHLEN + 1) /* smallest amount to put in cluster */
|
||||
#define MLEN ((int)(MSIZE - sizeof(struct m_hdr))) /* normal data len */
|
||||
#define MHLEN ((int)(MLEN - sizeof(struct pkthdr))) /* data len w/pkthdr */
|
||||
#define MINCLSIZE ((int)(MHLEN + 1)) /* smallest amount to put in cluster */
|
||||
#define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */
|
||||
|
||||
|
||||
@ -267,7 +267,6 @@ struct mbuf {
|
||||
#define M_PROTO3 0x0040 /* protocol-specific */
|
||||
#define M_PROTO4 0x0080 /* protocol-specific */
|
||||
#define M_PROTO5 0x0100 /* protocol-specific */
|
||||
#define M_NOTIFICATION M_PROTO5/* SCTP notification */
|
||||
#define M_SKIP_FIREWALL 0x4000 /* skip firewall processing */
|
||||
#define M_FREELIST 0x8000 /* mbuf is on the free list */
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#if !defined(__Userspace_os_FreeBSD)
|
||||
#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD)
|
||||
#include <sys/uio.h>
|
||||
#else
|
||||
#include <user_ip6_var.h>
|
||||
@ -56,7 +56,7 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin)
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
|
||||
#include <net/route.h>
|
||||
#endif
|
||||
/* local macros and datatypes used to get IP addresses system independently */
|
||||
@ -67,12 +67,12 @@
|
||||
void recv_thread_destroy(void);
|
||||
#define MAXLEN_MBUF_CHAIN 32 /* What should this value be? */
|
||||
#define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
|
||||
#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin)
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
|
||||
#define NEXT_SA(ap) ap = (struct sockaddr *) \
|
||||
((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (uint32_t)) : sizeof(uint32_t)))
|
||||
#endif
|
||||
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD)
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
|
||||
static void
|
||||
sctp_get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
|
||||
{
|
||||
@ -183,7 +183,7 @@ recv_function_route(void *arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -266,7 +266,7 @@ recv_function_route(void *arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -360,6 +360,8 @@ recv_function_raw(void *arg)
|
||||
}
|
||||
#endif
|
||||
SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */
|
||||
SCTP_STAT_INCR(sctps_recvpackets);
|
||||
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
|
||||
|
||||
if (n <= iovlen) {
|
||||
SCTP_BUF_LEN(recvmbuf[0]) = n;
|
||||
@ -404,44 +406,44 @@ recv_function_raw(void *arg)
|
||||
|
||||
/* SCTP does not allow broadcasts or multicasts */
|
||||
if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
|
||||
return NULL;
|
||||
return (NULL);
|
||||
}
|
||||
if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) {
|
||||
return NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
port = 0;
|
||||
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
#if defined(SCTP_WITH_NO_CSUM)
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
#else
|
||||
if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
|
||||
compute_crc = 0;
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
} else {
|
||||
SCTP_STAT_INCR(sctps_recvswcrc);
|
||||
}
|
||||
#endif
|
||||
SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
|
||||
SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
|
||||
|
||||
sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n,
|
||||
(struct sockaddr *)&src,
|
||||
(struct sockaddr *)&dst,
|
||||
sh, ch,
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
compute_crc,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
ecn,
|
||||
SCTP_DEFAULT_VRFID, port);
|
||||
if (recvmbuf[0]) {
|
||||
m_freem(recvmbuf[0]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
|
||||
m_free(recvmbuf[i]);
|
||||
}
|
||||
/* free the array itself */
|
||||
free(recvmbuf);
|
||||
#if defined (__Userspace_os_Windows)
|
||||
ExitThread(0);
|
||||
#else
|
||||
pthread_exit(NULL);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
@ -553,6 +555,8 @@ recv_function_raw6(void *arg)
|
||||
}
|
||||
#endif
|
||||
SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */
|
||||
SCTP_STAT_INCR(sctps_recvpackets);
|
||||
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
|
||||
|
||||
if (n <= iovlen) {
|
||||
SCTP_BUF_LEN(recvmbuf6[0]) = n;
|
||||
@ -597,9 +601,14 @@ recv_function_raw6(void *arg)
|
||||
src.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
src.sin6_port = sh->src_port;
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
#if defined(SCTP_WITH_NO_CSUM)
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
#else
|
||||
if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) {
|
||||
compute_crc = 0;
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
} else {
|
||||
SCTP_STAT_INCR(sctps_recvswcrc);
|
||||
}
|
||||
#endif
|
||||
SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
|
||||
@ -610,22 +619,18 @@ recv_function_raw6(void *arg)
|
||||
sh, ch,
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
compute_crc,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
0,
|
||||
SCTP_DEFAULT_VRFID, 0);
|
||||
if (recvmbuf6[0]) {
|
||||
m_freem(recvmbuf6[0]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
|
||||
m_free(recvmbuf6[i]);
|
||||
}
|
||||
/* free the array itself */
|
||||
free(recvmbuf6);
|
||||
#if defined (__Userspace_os_Windows)
|
||||
ExitThread(0);
|
||||
#else
|
||||
pthread_exit(NULL);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
@ -740,6 +745,8 @@ recv_function_udp(void *arg)
|
||||
n = ncounter;
|
||||
#endif
|
||||
SCTP_HEADER_LEN(udprecvmbuf[0]) = n; /* length of total packet */
|
||||
SCTP_STAT_INCR(sctps_recvpackets);
|
||||
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
|
||||
|
||||
if (n <= iovlen) {
|
||||
SCTP_BUF_LEN(udprecvmbuf[0]) = n;
|
||||
@ -789,10 +796,10 @@ recv_function_udp(void *arg)
|
||||
|
||||
/* SCTP does not allow broadcasts or multicasts */
|
||||
if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
|
||||
return NULL;
|
||||
return (NULL);
|
||||
}
|
||||
if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) {
|
||||
return NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/
|
||||
@ -802,9 +809,14 @@ recv_function_udp(void *arg)
|
||||
port = src.sin_port;
|
||||
src.sin_port = sh->src_port;
|
||||
dst.sin_port = sh->dest_port;
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
#if defined(SCTP_WITH_NO_CSUM)
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
#else
|
||||
if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
|
||||
compute_crc = 0;
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
} else {
|
||||
SCTP_STAT_INCR(sctps_recvswcrc);
|
||||
}
|
||||
#endif
|
||||
SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
|
||||
@ -815,22 +827,18 @@ recv_function_udp(void *arg)
|
||||
sh, ch,
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
compute_crc,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
0,
|
||||
SCTP_DEFAULT_VRFID, port);
|
||||
if (udprecvmbuf[0]) {
|
||||
m_freem(udprecvmbuf[0]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
|
||||
m_free(udprecvmbuf[i]);
|
||||
}
|
||||
/* free the array itself */
|
||||
free(udprecvmbuf);
|
||||
#if defined (__Userspace_os_Windows)
|
||||
ExitThread(0);
|
||||
#else
|
||||
pthread_exit(NULL);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
@ -945,6 +953,8 @@ recv_function_udp6(void *arg)
|
||||
n = ncounter;
|
||||
#endif
|
||||
SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */
|
||||
SCTP_STAT_INCR(sctps_recvpackets);
|
||||
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
|
||||
|
||||
if (n <= iovlen) {
|
||||
SCTP_BUF_LEN(udprecvmbuf6[0]) = n;
|
||||
@ -980,7 +990,7 @@ recv_function_udp6(void *arg)
|
||||
|
||||
/* SCTP does not allow broadcasts or multicasts */
|
||||
if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) {
|
||||
return NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
sh = mtod(udprecvmbuf6[0], struct sctphdr *);
|
||||
@ -990,9 +1000,14 @@ recv_function_udp6(void *arg)
|
||||
port = src.sin6_port;
|
||||
src.sin6_port = sh->src_port;
|
||||
dst.sin6_port = sh->dest_port;
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
#if defined(SCTP_WITH_NO_CSUM)
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
#else
|
||||
if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) {
|
||||
compute_crc = 0;
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
} else {
|
||||
SCTP_STAT_INCR(sctps_recvswcrc);
|
||||
}
|
||||
#endif
|
||||
SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
|
||||
@ -1006,18 +1021,15 @@ recv_function_udp6(void *arg)
|
||||
#endif
|
||||
0,
|
||||
SCTP_DEFAULT_VRFID, port);
|
||||
|
||||
if (udprecvmbuf6[0]) {
|
||||
m_freem(udprecvmbuf6[0]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
|
||||
m_free(udprecvmbuf6[i]);
|
||||
}
|
||||
/* free the array itself */
|
||||
free(udprecvmbuf6);
|
||||
#if defined (__Userspace_os_Windows)
|
||||
ExitThread(0);
|
||||
#else
|
||||
pthread_exit(NULL);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
@ -1074,7 +1086,7 @@ recv_thread_init(void)
|
||||
#else
|
||||
unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
|
||||
#endif
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD)
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
|
||||
if (SCTP_BASE_VAR(userspace_route) == -1) {
|
||||
if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) {
|
||||
SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno);
|
||||
@ -1375,7 +1387,7 @@ recv_thread_init(void)
|
||||
}
|
||||
#endif
|
||||
#if !defined(__Userspace_os_Windows)
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD)
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (SCTP_BASE_VAR(userspace_route) != -1) {
|
||||
int rc;
|
||||
@ -1467,7 +1479,7 @@ recv_thread_init(void)
|
||||
void
|
||||
recv_thread_destroy(void)
|
||||
{
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD)
|
||||
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (SCTP_BASE_VAR(userspace_route) != -1) {
|
||||
close(SCTP_BASE_VAR(userspace_route));
|
||||
@ -1507,4 +1519,6 @@ recv_thread_destroy(void)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
int foo;
|
||||
#endif
|
||||
|
@ -94,12 +94,7 @@ user_sctp_timer_iterate(void *arg)
|
||||
}
|
||||
SCTP_TIMERQ_UNLOCK();
|
||||
}
|
||||
#if defined (__Userspace_os_Windows)
|
||||
ExitThread(0);
|
||||
#else
|
||||
pthread_exit(NULL);
|
||||
#endif
|
||||
return NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user